/*
 * Copyright (c) 2005-2010 Saechsische AufbauBank - Foerderbank.
 * All Rights Reserved.
 *
 * This file may not be reproduced in any form or by any means
 * (graphic, electronic or mechanical) without written permission
 * from Saechsische AufbauBank - Foerderbank.
 *
 * $Id: ULCTableTreeSniplet.java 57977 2010-05-18 14:57:47Z a998127 $
 *
 * $Rev: 57977 $
 * $Date: 2010-05-18 16:57:47 +0200 (Di, 18 Mai 2010) $
 * $Author: a998127 $
 */
package de.sachsen.sab.it.prosab.main.test.ulcsniplets;

import java.util.Random;

import com.ulcjava.base.application.AbstractApplication;
import com.ulcjava.base.application.ULCFrame;
import com.ulcjava.base.application.ULCScrollPane;
import com.ulcjava.base.application.ULCTableTree;
import com.ulcjava.base.application.event.ActionEvent;
import com.ulcjava.base.application.event.IActionListener;
import com.ulcjava.base.application.event.ITreeExpansionListener;
import com.ulcjava.base.application.event.ITreeSelectionListener;
import com.ulcjava.base.application.event.TreeExpansionEvent;
import com.ulcjava.base.application.event.TreeSelectionEvent;
import com.ulcjava.base.application.tabletree.DefaultMutableTableTreeNode;
import com.ulcjava.base.application.tabletree.DefaultTableTreeModel;
import com.ulcjava.base.development.DevelopmentRunner;


/**
 * This sniplet can be used to reproduce a ULC-bug around the TreeExpansionListener and the ULCTableTree
 * selection handling. The expansion listener causes the selection listener to fail.
 * <ol>
 * <li>Right after the start each click on a node causes a selection change. A double-click causes the node
 * name to be printed.</li>
 * <li>To raise the bug just collapse the node "N20"</li>
 * <li>Now the click on a node does no longer trigger a selection event and a double-click on a node causes
 * always to print the name of node which was selected right before collapsing the "N20" node</li>
 * </ol>
 * 
 * @author <a href="mailto:christian.keiler@sab.sachsen.de">Christian Keiler</a>
 */
@SuppressWarnings("serial")
public class ULCTableTreeSniplet extends AbstractApplication {

	/**
	 * maximum depth
	 */
	private static final int LEVEL = 10;

	/**
	 * maximum number of sub nodes
	 */
	private static final int MAXCOUNT = 5;

	/**
	 * fixed random seed for deterministic test results
	 */
	private static final Random RAND = new Random(100);

	/**
	 * A main method to start the sample.
	 * 
	 * @param args no args supplied
	 */
	public static void main(String[] args) {
		DevelopmentRunner.setApplicationClass(ULCTableTreeSniplet.class);
		DevelopmentRunner.run();
	}

	/**
	 * recursively add nodes to a root
	 * 
	 * @param root the current root
	 * @param level the current level (also see {@link #LEVEL})
	 * @param count the count of subnodes to create
	 */
	static void addToNode(DefaultMutableTableTreeNode root, int level, int count) {
		if (level == LEVEL) {
			return;
		}
		for (int i = 0; i < count; i++) {
			final String nv = root.getValueAt(0).toString().concat(Integer.toString(i));
			final DefaultMutableTableTreeNode newRoot =
				new DefaultMutableTableTreeNode(new String[] {nv, Integer.toString(level)});
			addToNode(newRoot, level + 1, RAND.nextInt(MAXCOUNT));
			root.add(newRoot);
		}

	}

	/**
	 * expands the given tree
	 * 
	 * @param tree the tree
	 */
	private void expandTree(ULCTableTree tree) {
		int i = 0;
		int rowCount = tree.getRowCount();
		// expand completely
		while (i < rowCount) {
			tree.expandRow(i);
			i++;
			if (i == rowCount) {
				rowCount = tree.getRowCount();
			}
		}

	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void start() {
		final ULCTableTree tableTree = new ULCTableTree();
		DefaultMutableTableTreeNode root = new DefaultMutableTableTreeNode(new String[] {"N", "0"}); //$NON-NLS-1$ //$NON-NLS-2$
		addToNode(root, 0, MAXCOUNT);
		tableTree.setModel(new DefaultTableTreeModel(root, new String[] {"Node Name", "Depth"})); //$NON-NLS-1$ //$NON-NLS-2$
		expandTree(tableTree);
		tableTree.addActionListener(createActionListener());
		tableTree.addTreeExpansionListener(createTreeExpansionListener());
		tableTree.addTreeSelectionListener(createTreeSelectionListener());
		final ULCFrame frame = new ULCFrame();
		frame.setDefaultCloseOperation(ULCFrame.TERMINATE_ON_CLOSE);
		frame.getContentPane().add(new ULCScrollPane(tableTree));
		frame.setVisible(true);
	}

	/**
	 * @return the action listener
	 */
	private IActionListener createActionListener() {
		return new IActionListener() {

			@Override
			public void actionPerformed(ActionEvent event) {
				ULCTableTree tree = (ULCTableTree) event.getSource();
				System.out.println(tree.getLastSelectedPathComponent());
			}
		};
	}

	/**
	 * @return the selection listener
	 */
	private ITreeSelectionListener createTreeSelectionListener() {
		return new ITreeSelectionListener() {

			@Override
			public void valueChanged(TreeSelectionEvent event) {
				System.out.println("selected: " + event.getPath()); //$NON-NLS-1$
			}
		};
	}

	/**
	 * @return the expansion listener
	 */
	private ITreeExpansionListener createTreeExpansionListener() {
		return new ITreeExpansionListener() {

			@Override
			public void treeExpanded(TreeExpansionEvent event) {
				System.out.println("expanded: " + event.getPath()); //$NON-NLS-1$
			}

			@Override
			public void treeCollapsed(TreeExpansionEvent event) {
				System.out.println("collapsed: " + event.getPath()); //$NON-NLS-1$
			}
		};
	}
}
