package treestore;

import org.gnu.gtk.CellRenderer;
import org.gnu.gtk.CellRendererText;
import org.gnu.gtk.CellRendererToggle;
import org.gnu.gtk.DataColumn;
import org.gnu.gtk.DataColumnBoolean;
import org.gnu.gtk.DataColumnString;
import org.gnu.gtk.Gtk;
import org.gnu.gtk.Label;
import org.gnu.gtk.PolicyType;
import org.gnu.gtk.ScrolledWindow;
import org.gnu.gtk.SelectionMode;
import org.gnu.gtk.ShadowType;
import org.gnu.gtk.TreeIter;
import org.gnu.gtk.TreePath;
import org.gnu.gtk.TreeSelection;
import org.gnu.gtk.TreeStore;
import org.gnu.gtk.TreeView;
import org.gnu.gtk.TreeViewColumn;
import org.gnu.gtk.TreeViewColumnSizing;
import org.gnu.gtk.VBox;
import org.gnu.gtk.Window;
import org.gnu.gtk.WindowType;
import org.gnu.gtk.event.LifeCycleEvent;
import org.gnu.gtk.event.LifeCycleListener;
import org.gnu.gtk.event.TreeSelectionEvent;
import org.gnu.gtk.event.*;


/**
 * An example taken from gtk-demo to demonstrate the tree
 * store widget.
 */
public class TreeStoreExample implements TreeModelListener{
    // Data used in this example
    private static Object[][] janData = new Object[][] {
            {
                "New Years Day", Boolean.TRUE, Boolean.TRUE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Presidential Inaguration", Boolean.FALSE, Boolean.TRUE,
                Boolean.FALSE, Boolean.TRUE, Boolean.FALSE
            },
            {
                "Martin Luther King Jr. Day", Boolean.FALSE, Boolean.TRUE,
                Boolean.FALSE, Boolean.TRUE, Boolean.FALSE
            }
        };
    private static Object[][] febData = new Object[][] {
            {
                "Presidents' Day", Boolean.FALSE, Boolean.TRUE, Boolean.FALSE,
                Boolean.TRUE, Boolean.FALSE
            },
            {
                "Groundhog Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Valentine's Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.TRUE
            }
        };
    private static Object[][] marData = new Object[][] {
            {
                "National Tree Planting Day", Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE, Boolean.FALSE
            },
            {
                "St. Patrick's Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            }
        };
    private static Object[][] aprData = new Object[][] {
            {
                "April Fools' Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Army Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Earth Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Administrative Professionals' Day", Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE
            }
        };
    private static Object[][] mayData = new Object[][] {
            {
                "Nurses' Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "National Day of Prayer", Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE, Boolean.FALSE
            },
            {
                "Mothers' Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Armed Forces Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Memorial Day", Boolean.TRUE, Boolean.TRUE, Boolean.TRUE,
                Boolean.TRUE, Boolean.FALSE
            }
        };
    private static Object[][] junData = new Object[][] {
            {
                "June Fathers' Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Juneteenth (Liberation of Slaves", Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE, Boolean.FALSE
            },
            {
                "Flag Day", Boolean.FALSE, Boolean.TRUE, Boolean.FALSE,
                Boolean.TRUE, Boolean.FALSE
            }
        };
    private static Object[][] julData = new Object[][] {
            {
                "Parent's Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Independence Day", Boolean.FALSE, Boolean.TRUE, Boolean.FALSE,
                Boolean.TRUE, Boolean.FALSE
            }
        };
    private static Object[][] augData = new Object[][] {
            {
                "Air Force Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Coast Guard Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Friendship Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            }
        };
    private static Object[][] sepData = new Object[][] {
            {
                "Grandparents' Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Citizenship Day or Constitution Day", Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
            },
            {
                "Labor Day", Boolean.TRUE, Boolean.TRUE, Boolean.TRUE,
                Boolean.TRUE, Boolean.FALSE
            }
        };
    private static Object[][] octData = new Object[][] {
            {
                "National Children's Day", Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE, Boolean.FALSE
            },
            {
                "Bosses' Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Sweetest Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Mother-in-Law's Day", Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE, Boolean.FALSE
            },
            {
                "Navy Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Columbus Day", Boolean.FALSE, Boolean.TRUE, Boolean.FALSE,
                Boolean.TRUE, Boolean.FALSE
            },
            {
                "Halloween", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            }
        };
    private static Object[][] novData = new Object[][] {
            {
                "Marine Corps Day", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            },
            {
                "Veterans' Day", Boolean.TRUE, Boolean.TRUE, Boolean.TRUE,
                Boolean.TRUE, Boolean.FALSE
            },
            {
                "Thanksgiving", Boolean.FALSE, Boolean.TRUE, Boolean.FALSE,
                Boolean.TRUE, Boolean.FALSE
            }
        };
    private static Object[][] decData = new Object[][] {
            {
                "Pearl Harbor Rememberance Day", Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE, Boolean.FALSE
            },
            {
                "Christmas", Boolean.TRUE, Boolean.TRUE, Boolean.TRUE,
                Boolean.TRUE, Boolean.FALSE
            },
            {
                "Kwanzaa", Boolean.FALSE, Boolean.FALSE, Boolean.FALSE,
                Boolean.FALSE, Boolean.FALSE
            }
        };

    // model to hold the data
    TreeStore store = null;

    // tree control
    TreeView tree = null;
    DataColumn[] columns;

    public TreeStoreExample() {
        Window window = new Window(WindowType.TOPLEVEL);
        window.setTitle("Card planning sheet");
        window.addListener(new LifeCycleListener() {
        	public void lifeCycleEvent(LifeCycleEvent event) {}
			public boolean lifeCycleQuery(LifeCycleEvent event) {
				if (event.isOfType(LifeCycleEvent.Type.DESTROY) || 
						event.isOfType(LifeCycleEvent.Type.DELETE)) {
						Gtk.mainQuit();
				}
				return false;
			}
        });

        // add a vbox to hold the widgets for this window
        VBox vbox = new VBox(false, 8);
        vbox.setBorderWidth(8);
        window.add(vbox);

        // add a label at the top of the window
        Label label = new Label("Jeff's Holiday Card Planning Sheet", false);
        vbox.packStart(label, false, false, 0);

        // add a scrolled window to hold the tree control
        ScrolledWindow sw = new ScrolledWindow(null, null);
        sw.setShadowType(ShadowType.ETCHED_IN);
        sw.setPolicy(PolicyType.AUTOMATIC, PolicyType.AUTOMATIC);
        vbox.packStart(sw, true, true, 0);

        // create the tree model	
        columns = new DataColumn[] {
                new DataColumnString(), new DataColumnBoolean(),
                new DataColumnBoolean(), new DataColumnBoolean(),
                new DataColumnBoolean(), new DataColumnBoolean()
            };
        store = new TreeStore(columns);

        // add data to the model
        addMonth("January", janData);
        addMonth("February", febData);
        addMonth("March", marData);
        addMonth("April", aprData);
        addMonth("May", mayData);
        addMonth("June", junData);
        addMonth("July", julData);
        addMonth("August", augData);
        addMonth("September", sepData);
        addMonth("October", octData);
        addMonth("November", novData);
        addMonth("December", decData);

        // Create the tree view object
        tree = new TreeView(store);
        tree.setAlternateRowColor(true);

        // set the selection mode to enable the selection of multiple rows.
        TreeSelection ts = tree.getSelection();
        ts.setMode(SelectionMode.MULTIPLE);
		ts.addListener(new TreeSelectionListener() {
			public void selectionChangedEvent(TreeSelectionEvent event ) {
				TreeSelection mySelection = (TreeSelection)event.getSource();
				TreePath[] selected = mySelection.getSelectedRows();
				for (int index = 0; index < selected.length; index++) {
					TreeIter anIter = store.getIter(selected[index]);
					String col1 = store.getValue(anIter, (DataColumnString)columns[0]);
					System.out.println("Row selected:");
					System.out.println("    Col1: " + col1);
				}
			}			
		});


        // add the columns to the tree
        addColumns();

        // add the tree to the scrolled window
        sw.add(tree);

        // make sure all rows are expanded
        tree.addListener(new LifeCycleListener() {
                public void lifeCycleEvent(LifeCycleEvent event) {
                    if (event.isOfType(LifeCycleEvent.Type.REALIZE)) {
                        tree.expandAll();
                    }
                }
    			public boolean lifeCycleQuery(LifeCycleEvent event) {return false;}
            });

        window.setDefaultSize(650, 400);

        window.showAll();
    }

    /**
     * Add a month and all of the associated data to our model.
     */
    public void addMonth(String month, Object[][] data) {
        TreeIter iter = store.appendRow(null);

        // add the label row
        store.setValue(iter, (DataColumnString) columns[0], month);

        // Add the rows of data associated with this month.
        for (int i = 0; i < data.length; i++) {
            TreeIter child = store.appendRow(iter);
            Object[] row = data[i];

            for (int j = 0; j < row.length; j++) {
                if (row[j] instanceof Boolean) {
                    store.setValue(child, (DataColumnBoolean) columns[j],
                        ((Boolean) row[j]).booleanValue());
                } else {
                    store.setValue(child, (DataColumnString) columns[j],
                        row[j].toString());
                }
            }

            // add the columnt to indicate if it is visible
            //store.setValue(child, (DataColumnBoolean)columns[7], true);
        }
    }

    /**
     * Add the columns to the TreeView.
     */
    public void addColumns() {
        // create the first column - holiday names
        TreeViewColumn column = new TreeViewColumn();
        column.setTitle("Holiday");
        column.setClickable(true);
        tree.appendColumn(column);

        CellRenderer renderer = new CellRendererText();
        column.packStart(renderer, true);
        column.addAttributeMapping(renderer, CellRendererText.Attribute.TEXT,
            columns[0]);

        // Jeff column
        column = new TreeViewColumn();
        column.setTitle("Jeff");
        column.setClickable(true);
        column.setSizing(TreeViewColumnSizing.FIXED);
        column.setFixedWidth(70);
        tree.appendColumn(column);

        CellRendererToggle toggle = new CellRendererToggle();
        column.packStart(toggle, false);
        column.addAttributeMapping(toggle, CellRendererToggle.Attribute.ACTIVE,
            columns[1]);
        column.addAttributeMapping(toggle,
            CellRendererToggle.Attribute.ACTIVATABLE, columns[1]);

        // Kimberly column
        column = new TreeViewColumn();
        column.setTitle("Kimberly");
        column.setClickable(true);
        column.setSizing(TreeViewColumnSizing.FIXED);
        column.setFixedWidth(70);
        tree.appendColumn(column);

        toggle = new CellRendererToggle();
        column.packStart(toggle, false);
        column.addAttributeMapping(toggle, CellRendererToggle.Attribute.ACTIVE,
            columns[2]);
        column.addAttributeMapping(toggle,
            CellRendererToggle.Attribute.ACTIVATABLE, columns[2]);
        
        // Katherine column
        column = new TreeViewColumn();
        column.setTitle("Katherine");
        column.setClickable(true);
        column.setSizing(TreeViewColumnSizing.FIXED);
        column.setFixedWidth(70);
        tree.appendColumn(column);

        toggle = new CellRendererToggle();
        column.packStart(toggle, false);
        column.addAttributeMapping(toggle, CellRendererToggle.Attribute.ACTIVE,
            columns[3]);
        column.addAttributeMapping(toggle,
            CellRendererToggle.Attribute.ACTIVATABLE, columns[3]);
        
        
        // Jared column
        column = new TreeViewColumn();
        column.setTitle("Jared");
        column.setClickable(true);
        column.setSizing(TreeViewColumnSizing.FIXED);
        column.setFixedWidth(70);
        tree.appendColumn(column);

        toggle = new CellRendererToggle();
        column.packStart(toggle, false);
        column.addAttributeMapping(toggle, CellRendererToggle.Attribute.ACTIVE,
            columns[4]);
        column.addAttributeMapping(toggle,
            CellRendererToggle.Attribute.ACTIVATABLE, columns[4]);

        
        // Joseph column
        column = new TreeViewColumn();
        column.setTitle("Joseph");
        column.setClickable(true);
        column.setSizing(TreeViewColumnSizing.FIXED);
        column.setFixedWidth(70);
        tree.appendColumn(column);

        toggle = new CellRendererToggle();
        column.packStart(toggle, false);
        column.addAttributeMapping(toggle, CellRendererToggle.Attribute.ACTIVE,
            columns[5]);
        column.addAttributeMapping(toggle,
            CellRendererToggle.Attribute.ACTIVATABLE, columns[5]);
		tree.setReorderable( true );
		store.addListener(this );

	}

	public void treeModelEvent( TreeModelEvent event ){
		System.out.println("TreeModelEvent");
		System.err.println("TreeModelEvent");
		if (event.isOfType(TreeModelEvent.Type.ROWS_REORDERED)){
			System.out.println("Rows Reordered");
			System.out.println("Iter " + event.getTreeIter().toString());
			System.out.println("Path: " + event.getTreePath().toString() );
			Gtk.mainQuit();
		}
	}


    public static void main(String[] args) {
        Gtk.init(args);

        TreeStoreExample tse = new TreeStoreExample();

        Gtk.main();
    }
}
