/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on ----
!  AUTHOR(S): KOGA, Junichiro
!  File : JTreeTest.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */
package ciss.phase_viewer.projectbrowser;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Arrays;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

import org.apache.log4j.Logger;

import ciss.phase_viewer.mainpanel.InternalFrameChase;

public class JTreeTest extends InternalFrameChase {
    private static Logger logger = Logger.getLogger(JTreeTest.class.getName());
    JList list;
    JScrollPane spane1;
    JScrollPane spane2;
    JPanel panel;
    JSplitPane spltpane;
    JTree tree;
    DefaultMutableTreeNode treenode;

    Container cont;
    File[] roots;
    File[] templist;
    File[][] work = new File[512][];
    int curdir = 0;
    File temp;
    JButton btn1;
    boolean bFreezeFlag = false;

    // TreePathからパス文字列を生成するメソッド
    File getSubDirList(TreePath treepath) {
        if (treepath == null)
            return null;
        // まず、ルートディレクトリを取得する
        String string = treepath.getPathComponent(0).toString();
        // 次にパスカウントを取得する
        int count = treepath.getPathCount();
        // その後、残りのパス文字列を取得する
        for (int i = 1; i < count; i++) {
            string += treepath.getPathComponent(i).toString();
            if (i + 1 == count)
                break;
            else
                string += "\\"; // UNIXでは「/」を使う
        }
        logger.debug("subdirlist: " + string);
        return new File(string);
    }

    // リストと展開用のツリーを作成する
    void addExpandTree(TreePath tp, File file) {
        // リストを更新する
        if (file == null)
            return;

        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tp
                .getLastPathComponent();
        logger.debug(node.toString());
        if (node == null)
            return;

        // ディレクトリの場合は、リストも更新する
        if (file.isDirectory()) {
            // リストを更新する
            // /////////////////////////////////////////
            // サブディレクトリをリストする
            templist = file.listFiles();
            // リストが空の場合は処理しない
            if (templist.length == 0)
                return;
            curdir++;
            work[curdir] = templist;
            Arrays.sort(work[curdir]);
            list.setListData(work[curdir]);
            // /////////////////////////////////////////

            // 次に、ツリーを更新する
            // このノードの現在のすべての子ノードを除去する
            node.removeAllChildren();

            // 2レベルの子ノードを追加する
            for (int i = 0; i < work[curdir].length; i++) {
                DefaultMutableTreeNode temp = new DefaultMutableTreeNode(
                        work[curdir][i].getName());
                logger.debug(temp.toString());
                node.add(temp);

                if (work[curdir][i].isDirectory()) {
                    // このディレクトリのリストを作成する
                    File[] files = work[curdir][i].listFiles();
                    // リストが空の場合は処理しない
                    if (files == null || files.length == 0)
                        continue;
                    // 昇順にソートする
                    Arrays.sort(files);

                    // リストの各ノードをツリーに追加する
                    for (int j = 0; j < files.length; j++) {
                        DefaultMutableTreeNode tempsub = new DefaultMutableTreeNode(
                                files[j].getName());
                        // このノードを追加する
                        temp.add(tempsub);
                    }
                }
            }
        }
    }

    // 折り畳んだ後のリストを表示する
    void showDirectory(TreePath tp, File file) {
        // リストを更新する
        if (file == null) {
            templist = new File[1];
            curdir++;
            work[curdir] = templist;
            list.setListData(work[curdir]);
            return;
        }
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tp
                .getLastPathComponent();
        if (node == null)
            return;

        // ディレクトリの場合は、リストを更新する
        if (file.isDirectory()) {
            // サブディレクトリをリストする
            templist = file.listFiles();
            // リストが空の場合は処理しない
            if (templist.length == 0)
                return;
            curdir++;
            work[curdir] = templist;
            Arrays.sort(work[curdir]);
            list.setListData(work[curdir]);
        }
    }

    public static void main(String args[]) {

        // MyFirstJavaオブジェクトを作成する
        JTreeTest window = new JTreeTest();

        // ウィンドウのサイズを指定する
        window.setSize(400, 200);

        // ////////////////////////////////////////////////////
        // デフォルトの終了処理を設定する
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // ////////////////////////////////////////////////////

        // ウィンドウを表示する
        window.setVisible(true);
    }

    // MyFirstJavaクラスのデフォルトコンストラクタを実装する
    public JTreeTest() {
        super("ツリーとリストを使ったディレクトリ探索", true, true, true, true, new Dimension(600,
                300));

        // コンテントペインを取得する
        cont = getContentPane();
        ((BorderLayout) cont.getLayout()).setVgap(5);

        panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        btn1 = new JButton("履歴");
        btn1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                --curdir;
                if (curdir == -1) {
                    curdir = 0;
                    Toolkit.getDefaultToolkit().beep();
                }
                // この変更のイベント処理をフリーズする
                bFreezeFlag = true;
                list.setListData(work[curdir]);
            }
        });
        panel.add(btn1);
        cont.add(panel, "North");

        // 左側のスクロールペインを作成する
        spane1 = new JScrollPane();

        // ルートディレクトリを取得する
        roots = File.listRoots();
        // ルートディレクトリのノードを作成する
        treenode = new DefaultMutableTreeNode(roots[1]); // UNIXでは、roots[0]
        // ルートパスのノードを使ってツリーを作成する
        tree = new JTree(treenode);
        // 最初はリーフにならないよう、ダミーの子ツリーを追加しておく
        treenode.add(new DefaultMutableTreeNode(""));

        // TreeWillExpandListenerリスナを登録、実装する
        tree.addTreeWillExpandListener(new TreeWillExpandListener() {
            // ツリーが展開されようとしている
            public void treeWillExpand(TreeExpansionEvent e) {
                // 現在のツリーパスを取得する
                TreePath tp = e.getPath();
                // パス文字列を生成する
                File file = getSubDirList(tp);
                // リストを更新して、展開用のツリーを作成する
                addExpandTree(tp, file);
            }

            // ツリーが折り畳まれようとしている
            public void treeWillCollapse(TreeExpansionEvent e) {
                // 現在のツリーパスを取得する
                TreePath tp = e.getPath().getParentPath();
                // パス文字列を生成する
                File file = getSubDirList(tp);
                // 折り畳んだパスのリストを表示する
                showDirectory(tp, file);
            }
        });

        // ツリーをスクロールペインに格納する
        spane1.setViewportView(tree);

        // 右側のスクロールペインを作成する
        spane2 = new JScrollPane();

        // リストを作成する
        list = new JList(work[curdir]);

        // 最初は空のリストを表示する
        templist = new File[1];
        work[curdir] = templist;
        list.setListData(work[curdir]);

        // リストセレクションリスナを登録、実装する
        list.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                // このケースは処理しない
                if (bFreezeFlag) {
                    bFreezeFlag = false;
                    return;
                }
                if (list.getSelectedValue() == null)
                    return;
                // ファイルの場合
                if (((File) list.getSelectedValue()).isFile()) {
                    JOptionPane.showMessageDialog(cont, list.getSelectedValue()
                            + "が選択されました");
                }
            }
        });
        // リストをスクロールペインに格納する
        spane2.setViewportView(list);

        // スプリットペインを作成する
        spltpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, spane1,
                spane2);
        // ワンタッチエキスパンダを装着する
        spltpane.setOneTouchExpandable(true);
        // ディバイダを水平中央位置に設定する
        spltpane.setDividerLocation(300);
        cont.add(spltpane, "Center");
    }
}
