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, TreeViewListener {
    // 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);
        tree.addListener(this);

    }

    public void treeModelEvent(TreeModelEvent event) {
        System.out.println("TreeModelEvent: " + event.getType().getName());

        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 void treeViewEvent(TreeViewEvent event) {
        System.out.println("TreeViewEvent: " + event.getType().getName());

        if (event.isOfType(TreeViewEvent.Type.MOVE_CURSOR)) {
            System.out.println("    Step: " + event.getMovementStep());
            System.out.println("    By: " + event.getHowMany());
        }
    }

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

        TreeStoreExample tse = new TreeStoreExample();

        Gtk.main();
    }
}
