/* $Id: SpreadSelectionTree.java 125 2011-03-09 09:49:51Z ohura $ */
/* TODO 
 * Spread Selection List は、 2, 12-18, 3, 6 のような表現。クラスとしては、
 * 名前付きのそういうデータのクラス。それをscopeに指定してサーチすればよい。
 * これは、その SpreadSelectionList を作るための GUI editor として位置付ける。
 * 起動したら SpreadTree の editor は disable に。
 * Make とかのボタンで spreadSelectionList を吐き、SpreadTree の editor は元の状態に。
 * この窓を閉じたときには結果を吐かないが、SpreadTree の editor は元の状態に。 -> 清水：閉じた event はどうとる？
 * usersNote にも適用できるようにする。
 * Edit 機能を追加： SpreadSelectionList を load, folder で選べる。複数で選べる。
 * folder の表示は？： folder 以下の一部が選ばれていたらアイコンを変えるか？やりすぎ？
 * SpraedTree を編集した際に, 対応する SpreadSelectionList も
 * 自動的に変更されるようにする。
 * また、SpreadSelectionTreeeは singleton である必要はない。今は、
 * ActionListener が、適切な tree を get するためにそう作ってあるが、ActionListener を、
 * 正しく、tree につけられれば、必要はない。
 */

package smart_gs.spread_selection;

/*
 * 
 Made from a source in
 Definitive Guide to Swing for Java 2, Second Edition
 By John Zukowski     
 ISBN: 1-893115-78-X
 Publisher: APress
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.EventObject;

import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;

import smart_gs.logical.Spread;
import smart_gs.logical.SpreadDirectory;
import smart_gs.logical.SpreadTree;
import smart_gs.spread_selection.GUISaveSpreadSelectionListAction;
import smart_gs.spread_selection.SpreadSelectionTreePanel;
import smart_gs.swingui.WorkspaceWindow;

public class SpreadSelectionTree extends JTree {
	private DefaultMutableTreeNode rootNode;

	public SpreadSelectionTree() {
		DefaultMutableTreeNode spreadTreeRootNode = SpreadTree.getInstance().getRootNode();
		rootNode = selectionTreeRootNode(spreadTreeRootNode);
		JTree tmpTree = new JTree(rootNode);
		this.setModel(tmpTree.getModel());
		((DefaultTreeModel)((JTree)this).getModel()).reload();
		CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
		this.setCellRenderer(renderer);
		this.setCellEditor(new CheckBoxNodeEditor(this));
		this.setEditable(true);
	}

//	returns the list of the indexes of the checked nodes
	public ArrayList<Integer> selectionList () {
		return (new SelectionListCollector()).collect();}

	class SelectionListCollector {
		ArrayList<Integer> selectionList = new ArrayList();

		ArrayList<Integer> collect() {
			selectionList.clear();
			collectIndexsOfCheckedSpreads(rootNode);
			return selectionList;
		}

		void collectIndexsOfCheckedSpreads(DefaultMutableTreeNode parentNode) {
			Enumeration enumeration = parentNode.children();
			while (enumeration.hasMoreElements()) {
				DefaultMutableTreeNode childrenNode = (DefaultMutableTreeNode) enumeration
				.nextElement();
				Object usrObj = childrenNode.getUserObject();
				if (usrObj instanceof CheckBoxNode) {
					if (((CheckBoxNode) usrObj).isSelected()) {
						Integer index = ((CheckBoxNode) usrObj).getIndex();
						selectionList.add(index);
					}
				} else {
					collectIndexsOfCheckedSpreads(childrenNode);
				}
			}
		}
	}
	

		public DefaultMutableTreeNode getRootNode() {
			return rootNode;
		}

//		Construct a new tree model from the root node of a tree by replacing
//		every leaf node by a CheckBoxNode with the same index and name.
//		It returns the root node of the new tree model.
//		The new tree model is deeply copied. Thus it does not share any node with the old one.
		private DefaultMutableTreeNode selectionTreeRootNode(DefaultMutableTreeNode node) {
			Object usrObj = node.getUserObject();
			DefaultMutableTreeNode resultNode = null;
			if (usrObj instanceof Spread) {
				resultNode = new DefaultMutableTreeNode(new CheckBoxNode(((Spread) usrObj).toString(), 
						false,((Spread) usrObj).getPageViewIndex()));
			} else if (usrObj instanceof SpreadDirectory) {
				resultNode = new DefaultMutableTreeNode(((SpreadDirectory) usrObj).toString());				
				Enumeration<DefaultMutableTreeNode> enumeration = node.children();
				while(enumeration.hasMoreElements()){
					resultNode.add(selectionTreeRootNode((DefaultMutableTreeNode)(enumeration.nextElement())));
				}
			} else {
				System.out.println("Illegal Spread Tree");
			}
			return resultNode;		
		}
	}

	class CheckBoxNodeRenderer implements TreeCellRenderer {
		private JCheckBox leafRenderer = new JCheckBox();

		private DefaultTreeCellRenderer nonLeafRenderer = new DefaultTreeCellRenderer();

		Color selectionBorderColor, selectionForeground, selectionBackground,
		textForeground, textBackground;

		protected JCheckBox getLeafRenderer() {
			return leafRenderer;
		}

		public CheckBoxNodeRenderer() {
			Font fontValue;
			fontValue = UIManager.getFont("Tree.font");
			if (fontValue != null) {
				leafRenderer.setFont(fontValue);
			}
			Boolean booleanValue = (Boolean) UIManager
			.get("tree.drawsFocusBorderAroundIcon");
			leafRenderer.setFocusPainted((booleanValue != null)
					&& (booleanValue.booleanValue()));

			selectionBorderColor = UIManager.getColor("tree.selectionBorderColor");
			selectionForeground = UIManager.getColor("tree.selectionForeground");
			selectionBackground = UIManager.getColor("tree.selectionBackground");
			textForeground = UIManager.getColor("tree.textForeground");
			textBackground = UIManager.getColor("tree.textBackground");
		}

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

			Component returnValue;
			if (leaf) {

				String stringValue = tree.convertValueToText(value, selected,
						expanded, leaf, row, false);
				leafRenderer.setText(stringValue);
				leafRenderer.setSelected(false);

				leafRenderer.setEnabled(tree.isEnabled());

				if (selected) {
					leafRenderer.setForeground(selectionForeground);
					leafRenderer.setBackground(selectionBackground);
				} else {
					leafRenderer.setForeground(textForeground);
					leafRenderer.setBackground(textBackground);
				}

				if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
					Object userObject = ((DefaultMutableTreeNode) value)
					.getUserObject();
					if (userObject instanceof CheckBoxNode) {
						CheckBoxNode node = (CheckBoxNode) userObject;
						leafRenderer.setText(node.getText());
						leafRenderer.setSelected(node.isSelected());
					}
				}
				returnValue = leafRenderer;
			} else {
				returnValue = nonLeafRenderer.getTreeCellRendererComponent(tree,
						value, selected, expanded, leaf, row, hasFocus);
			}
			return returnValue;
		}
	}

	class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor {

		CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();

		ChangeEvent changeEvent = null;

		JTree tree;

		public CheckBoxNodeEditor(JTree tree) {
			this.tree = tree;
		}

		public Object getCellEditorValue() {
			JCheckBox checkbox = renderer.getLeafRenderer();
			CheckBoxNode checkBoxNode = new CheckBoxNode(checkbox.getText(),
					checkbox.isSelected(), Integer.valueOf(((checkbox.getText()).split(":",2))[0]));
			return checkBoxNode;
		}

		public boolean isCellEditable(EventObject event) {
			boolean returnValue = false;
			if (event instanceof MouseEvent) {
				MouseEvent mouseEvent = (MouseEvent) event;
				TreePath path = tree.getPathForLocation(mouseEvent.getX(),
						mouseEvent.getY());
				if (path != null) {
					Object node = path.getLastPathComponent();
					if ((node != null) && (node instanceof DefaultMutableTreeNode)) {
						DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
						Object userObject = treeNode.getUserObject();
						returnValue = ((treeNode.isLeaf()) && (userObject instanceof CheckBoxNode));
					}
				}
			}
			return returnValue;
		}

		public Component getTreeCellEditorComponent(JTree tree, Object value,
				boolean selected, boolean expanded, boolean leaf, int row) {

			Component editor = renderer.getTreeCellRendererComponent(tree, value,
					true, expanded, leaf, row, true);

			// editor always selected / focused
			ItemListener itemListener = new ItemListener() {
				public void itemStateChanged(ItemEvent itemEvent) {
					if (stopCellEditing()) {
						fireEditingStopped();
					}
				}
			};
			if (editor instanceof JCheckBox) {
				((JCheckBox) editor).addItemListener(itemListener);
			}

			return editor;
		}
	}

	class CheckBoxNode {
		String text;
		boolean selected;
		int index;

		public CheckBoxNode(String text, boolean selected, int index) {
			this.text = text;
			this.selected = selected;
			this.index = index;
		}

		public boolean isSelected() {
			return selected;
		}

		public void setSelected(boolean newValue) {
			selected = newValue;
		}


		public String getText() {
			return text;
		}

		public void setText(String newValue) {
			text = newValue;
		}

		public int getIndex() {
			return index;
		}

		public void setIndex(int newValue) {
			index = newValue;
		}

		public String toString() {
			return getClass().getName() + "[" + text + "/" + selected + "]";
		}
	}
