/*
 * Java-Gnome Bindings Library
 *
 * Copyright 1998-2004 the Java-Gnome Team, all rights reserved.
 *
 * The Java-Gnome bindings library is free software distributed under
 * the terms of the GNU Library General Public License version 2.
 */

package org.gnu.gtk;

import java.util.Vector;

import org.gnu.glib.EventMap;
import org.gnu.glib.GObject;
import org.gnu.glib.Type;
import org.gnu.gtk.event.GtkEventType;
import org.gnu.gtk.event.TreeViewEvent;
import org.gnu.gtk.event.TreeViewListener;

/**
 * The TreeView object is a widget for displaying trees and lists. The sole
 * purpose of this widget is for displaying the data on the screen and setting
 * other parts of the view using the associated objects. 
 *
 * <h1>Gtk Tree and List Widgets Overview</h1>
 * <p>The standard tree and list widgets in Gtk are very powerful, but somewhat
 * complex. For your conveniance, the Java-Gnome project has derived a number of
 * simpler classes for common uses of these widgets. 
 * <dl>
 * <dt>{@link SimpleList}
 * <dd>A single column list of string values.
 * <dt>todo...
 * <dd>todo...
 * </dl>
 * <p>If you choose not to use those, or your requirements are such that you
 * cannot use them, you will have to learn how to use the full objects. 
 * 
 * <h2>{@link TreeView}</h2>
 * <p>There is only one widget which is placed in any applications to create
 * trees, lists and tables. This is the {@link TreeView}. An application can
 * have any number of treeviews and they can be placed as can normal widgets.
 * The data for the widget, and the method in which it is displayed is
 * controlled by other classes. Gtk has been designed so that any number of
 * treeview widgets can be linked to the same data store. {@link
 * TreeViewColumn}s, {@link CellRenderer}s and {@link TreeSelection}s are
 * created for each view, so Views can use the same data store but have their
 * own column layout, data display within those columns (linked to any of the
 * dataBlocks in the store); and their own selections.
 *
 * <h2>{@link TreeModel}</h2>
 * <p>Models are used to store data. Data is stored in what could be considered
 * a table. There are a number of {@link DataColumn}s, which could be considered as
 * data columns (in fact, in the C version of gtk, they are always refered to as
 * columns; but this can get confused with TreeViewColumns which are quite a
 * different matter). These dataBlocks each store one type of data
 * (String, boolean, int, etc.). The 'rows' of the data table, or the individual
 * records in the data store are accessible using iterators called {@link
 * TreeIter}s. These are used extensively in many methods. Setting data involves
 * getting an iterator (usually be creating a new row) and then setting the
 * value for each of the dataBlocks. The ordering of these dataBlocks has
 * absolutely no meaning - you can decide exactly which blocks are used on
 * screen by setting Attribute mappings to the CellRenderers which render data
 * on the screen (see below).
 * <p>Currently, there are two implementations of {@link TreeModel}
 * <p>{@link ListStore} - This is used for tables and lists. Data is organised
 * in rows and columns.
 * <p>{@link TreeStore} - This is for the hierarchical trees. Data is organised
 * using {@link TreePath}'s.
 *
 * <h2>{@link TreeViewColumn}</h2>
 * <p>Both trees and lists can have multiple columns of data. Columns are added
 * and removed using the {@link TreeView} class. Columns are objects which
 * determine how the data is displayed. They have settings such as the column
 * title, whether the column can be resized, and even whether the columns can be
 * reorganized (by dragging the columns). Each {@link TreeView} widget has it's
 * own set of columns. Determining how the data is displayed in the columns is
 * done by CellRenderers (see below). Any number of renderers can be added to
 * the same column
 * 
 * <h2>{@link CellRenderer}</h2>
 * <p>Tree and list `cells' may contain a large variety of data types.
 * Determining how they are displayed is done by the CellRenderer family of
 * classes. If the data is unusual, or you want to combine a number of data
 * types in a single column, you may construct your own renderer. However, you
 * are recommended to stick with the regular choices:
 * <dl>
 * <dt>{@link CellRendererPixbuf}
 * <dd>
 * <dt>{@link CellRendererText}
 * <dd>For displaying Strings
 * <dt>{@link CellRendererToggle}
 * <dd>For displaying boolean data, either as individual checkboxes or as radio
 * buttons.
 * </dl>
 * <p>The CellRenderer's need data to be able to display. This is set using the
 * {@link TreeViewColumn#addAttributeMapping(CellRenderer,
 * CellRendererAttribute, int)}. The renderer attributes vary with each
 * renderer, for example CellRendererText has a TEXT attribute for the text the
 * be displayed. The final parameter is for the dataBlock in the store in which
 * the data is contained.
 * 
 *
 * <p>Java-Gnome comes with a number of simple example applications involving trees.
 * They may be useful for learning the functionality of these classes.
 *
 * @author Mark Howard &lt;mh@debian.org&gt;
 */
public class TreeView extends Container {

	/**
	 * Create a new TreeView object.
	 */
	public TreeView() {
		super(gtk_tree_view_new());
		initializeEventHandlers();
	}
	
	/**
	 * Creates a new tree view from a native handle
	 */
	public TreeView(int handle) {
		super(handle);
		initializeEventHandlers();
	}

	/**
	 * Creates a new TreeView Widget with the initial model set
	 */
	public TreeView(TreeModel model) {
		super(gtk_tree_view_new_with_model(model.getHandle()));
		initializeEventHandlers();
	}

	/**
	 * Returns the model associated with this tree.
	 */
	public TreeModel getModel() {
		int hndl = gtk_tree_view_get_model(getHandle());
		GObject obj = retrieveGObject(hndl);
		if (null != obj)
			return (TreeModel)obj;
		return new TreeModel(hndl);
	}

	/**
	 * Appends column to the list of columns.
	 *
	 * @param column The GtkTreeViewColumn to add.
	 * @return The number of columns in tree_view after appending.
	 */
	public int appendColumn(TreeViewColumn column) {
		return gtk_tree_view_append_column(getHandle(), column.getHandle());
	}

	/**
	 * This inserts the column into the tree_view at position. If position is -1, then the column is inserted at the end.
	 *
	 * @param column The GtkTreeViewColumn to be inserted.
	 * @param position The position to insert column in.
	 * @return The number of columns in tree_view after insertion.
	 */
	public int insertColumn(TreeViewColumn column, int position) {
		return gtk_tree_view_insert_column(getHandle(), column.getHandle(), position);
	}

	/**
	 * Removes column from tree_view.
	 * @param column The GtkTreeViewColumn to remove.
	 * @return The number of columns in tree_view after removing.
	 */
	public int removeColumn(TreeViewColumn column) {
		return gtk_tree_view_remove_column(getHandle(), column.getHandle());
	}

	/**
	 * Gets the TreeSelection associated with this widget
	 */
	public TreeSelection getSelection() {
		int hndl = gtk_tree_view_get_selection(getHandle());
		GObject obj = retrieveGObject(hndl);
		if (null != obj)
			return (TreeSelection)obj;
		return new TreeSelection(hndl);
	}

	/**
	 * Gets the GtkAdjustment currently being used for the horizontal aspect.
	 * @return A GtkAdjustment object, or NULL if none is currently being used.
	 */
	public Adjustment getHAdjustment() {
		int hndl = gtk_tree_view_get_hadjustment(getHandle());
		GObject obj = retrieveGObject(hndl);
		if (null != obj)
			return (Adjustment)obj;
		return new Adjustment(hndl);
	}

	/**
	 * Sets the Adjustment for the current horizontal aspect.
	 */
	public void setHAdjustment(Adjustment hadj) {
		gtk_tree_view_set_hadjustment(getHandle(), hadj.getHandle());
	}

	/**
	 * Gets the Adjustment currently being used for the vertical aspect.
	 */
	public Adjustment getVAdjustment() {
		return new Adjustment(gtk_tree_view_get_vadjustment(getHandle()));
	}

	/**
	 * Sets the Adjustment for the current vertical aspect.
	 */
	public void setVAdjustment(Adjustment vadj) {
		gtk_tree_view_set_vadjustment(getHandle(), vadj.getHandle());
	}

	/**
	 * Sets the the visibility state of the headers.
	 * @param headersVisible TRUE if the headers are visibl
	 */
	public void setHeadersVisible(boolean headersVisible) {
		gtk_tree_view_set_headers_visible(getHandle(), headersVisible);
	}
	
	/**
	 * Returns true if the headers on the TreeView are visible.
	 * @return
	 */
	public boolean getHeadersVisible() {
		return gtk_tree_view_get_headers_visible(getHandle());
	}

	/**
	 * Allow the column title buttons to be clicked.
	 * @param setting TRUE if the columns are clickable.
	 */
	public void setHeadersClickable(boolean setting) {
		gtk_tree_view_set_headers_clickable(getHandle(), setting);
	}

	/**
	 * This function tells GTK+ that the user interface for your application 
	 * requires users to read across tree rows and associate cells with one 
	 * another. By default, GTK+ will then render the tree with alternating 
	 * row colors. Do not use it just because you prefer the appearance of
	 * the ruled tree; that's a question for the theme. Some themes will 
	 * draw tree rows in alternating colors even when rules are turned off, 
	 * and users who prefer that appearance all the time can choose those
	 * themes. You should call this function only as a semantic hint to 
	 * the theme engine that your tree makes alternating colors useful 
	 * from a functional standpoint (since it has lots of columns, 
	 * generally).
	 * @param setting TRUE if the tree requires reading across rows
	 */
	public void setAlternateRowColor(boolean setting) {
		gtk_tree_view_set_rules_hint(getHandle(), setting);
	}
	
	public boolean getAlternateRowColor() {
		return gtk_tree_view_get_rules_hint(getHandle());
	}

	/**
	 * Gets the column at the given position in the tree view.
	 * @param n  The position of the column, counting from 0.
	 * @return The TreeViewColumn, or <code>null</code> if the position is outside the range 
	 * of columns.
	 */
	public TreeViewColumn getColumn(int position) {
		int h = gtk_tree_view_get_column(getHandle(), position);
		if (h < 0)
			return null;
		GObject obj = retrieveGObject(h);
		if (null != obj)
			return (TreeViewColumn)obj;
		return new TreeViewColumn(h);
	}

	/**
	 * Moves column to be after to baseColumn. If baseColumn is NULL, then 
	 * column is placed in the first position.
	 * @param column The GtkTreeViewColumn to be moved.
	 * @param baseColumn The GtkTreeViewColumn to be moved relative to, or 
	 * NULL.
	 */
	public void moveColumn(TreeViewColumn column, TreeViewColumn baseColumn) {
		gtk_tree_view_move_column_after(getHandle(), column.getHandle(), baseColumn.getHandle());
	}

	/**
	 * Sets the column to draw the expander arrow at. 
	 * If column is NULL, then the expander arrow is always at the first visible 
	 * column.
	 * @param column NULL, or the column to draw the expander arrow at.
	 */
	public void setExpanderColumn(TreeViewColumn column) {
		gtk_tree_view_set_expander_column(getHandle(), column.getHandle());
	}
	
	public TreeViewColumn getExpanderColumn() {
		int hndl = gtk_tree_view_get_expander_column(getHandle());
		if (hndl < 0)
			return null;
		GObject obj = retrieveGObject(hndl);
		if (null != obj)
			return (TreeViewColumn)obj;
		return new TreeViewColumn(hndl);
	}

	/**
	 * todo: set column drag function
	 * Interface.
	 */

	/**
	 * Moves the alignments of the view to the position specified by column and 
	 * path. . rowAlign determines where the row is placed, 
	 * and colAlign determines where column is placed. Both are expected to be 
	 * between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means 
	 * right/bottom alignment, 0.5 means center.
	 *
	 * @param path The path of the row to move to
	 * @param column The TreeViewColumn to move horizontally to
	 * @param rowAlign The vertical alignment of the row specified by path.
	 * @param colAlign : The horizontal alignment of the column specified by 
	 * column.
	 */
	public void scrollToCell(TreePath path, TreeViewColumn column, double rowAlign, double colAlign) {
		gtk_tree_view_scroll_to_cell(getHandle(), path.getHandle(), column.getHandle(), true, rowAlign, colAlign);
	}
	
	/**
	 * Scrolls the TreeView such that the top-left corner of the visible
	 * area is x, y, where x and y are specified in tree window coordinates.
	 * If either x or y are -1 then that direction isn't scrolled. 
	 * @param x
	 * @param y
	 */
	public void scrollToPoint(int x, int y) {
		gtk_tree_view_scroll_to_point(getHandle(), x, y);
	}

	/**
	 * Moves the alignments of the view to the position specified by column and 
	 * path. 
	 * @param path The path of the row to move to
	 * @param column The TreeViewColumn to move horizontally to
	 */
	public void scrollToCell(TreePath path, TreeViewColumn column) {
		gtk_tree_view_scroll_to_cell(getHandle(), path.getHandle(), column.getHandle(), false, 0, 0);
	}

	/**
	 * Moves the alignments of the view to the position specified by column 
	 *
	 * @param column The TreeViewColumn to move horizontally to
	 */
	public void scrollToCell(TreeViewColumn column) {
		gtk_tree_view_scroll_to_cell(getHandle(), 0, column.getHandle(), false, 0, 0);
	}

	/**
	 * Moves the alignments of the view to the position specified by 
	 * path.
	 * @param path The path of the row to move to, or NULL.
	 */
	public void scrollToCell(TreePath path) {
		gtk_tree_view_scroll_to_cell(getHandle(), path.getHandle(), 0, false, 0, 0);
	}

	/**
	 * Sets the current keyboard focus to be at path, and selects it. This is 
	 * useful when you want to focus the user's attention on a particular 
	 * row. If column is specified, and 
	 * startEditing is TRUE, then editing should be started in the specified 
	 * cell. This function is often followed by {@link Widget#grabFocus()}
	 * in order to give keyboard focus to the widget. Please note that editing
	 * can only happen when the widget is realized.
	 * @param path A TreePath
	 * @param focusColumn A TreeViewColumn, or NULL
	 * @param startEditing TRUE if the specified cell should start being edited.
	 */
	public void setCursor(TreePath path, TreeViewColumn focusColumn, boolean startEditing) {
		gtk_tree_view_set_cursor(getHandle(), path.getHandle(), focusColumn.getHandle(), startEditing);
	}

	/**
	 * Returns the current path
	 */
	public TreePath getCursorPath() {
		int[] path = new int[1];
		int[] column = new int[1];
		gtk_tree_view_get_cursor(getHandle(), path, column);
		return new TreePath(path[0]);
	}

	/** 
	 * Returns the current column 
	 */
	public TreeViewColumn getCursorColumn() {
		int[] path = new int[1];
		int[] column = new int[1];
		gtk_tree_view_get_cursor(getHandle(), path, column);
		GObject obj = retrieveGObject(column[0]);
		if (null != obj)
			return (TreeViewColumn)obj;
		return new TreeViewColumn(column[0]);
	}

	/**
	 * Activates the cell determined by path and column.
	 * @param path The TreePath to be activated.
	 * @param column The TreeViewColumn to be activated.
	 */
	public void activateCell(TreePath path, TreeViewColumn column) {
		gtk_tree_view_row_activated(getHandle(), path.getHandle(), column.getHandle());
	}

	/**
	 * Recursively expands all nodes
	 */
	public void expandAll() {
		gtk_tree_view_expand_all(getHandle());
	}

	/**
	 * Recursively collapses all visible, expanded nodes.
	 */
	public void collapseAll() {
		gtk_tree_view_collapse_all(getHandle());
	}

	/**
	 * Opens the row so its children are visible.
	 * @param path Path to a row
	 * @param openAll Whether to recursively expand, or just expand immediate 
	 * children
	 * @return TRUE if the row existed and had children
	 */
	public boolean expandRow(TreePath path, boolean openAll) {
		return gtk_tree_view_expand_row(getHandle(), path.getHandle(), openAll);
	}

	/**
	 * Collapses a row (hides its child rows, if they exist).
	 * @param path Path to a row in the view
	 * @return TRUE if the row was collapsed.
	 */
	public boolean collapseRow(TreePath path) {
		return gtk_tree_view_collapse_row(getHandle(), path.getHandle());
	}

	/**
	 * TODO: map_expanded_rows
	 */

	/**
	 * Returns TRUE if the node pointed to by path is expanded.
	 * @param path A TreePath to test expansion state.
	 * @return TRUE if path is expanded.
	 */
	public boolean getRowExpanded(TreePath path) {
		return gtk_tree_view_row_expanded(getHandle(), path.getHandle());
	}

	/**
	 * This function is a convenience function to allow you to reorder models 
	 * that support the DragSourceIface and the DragDestIface. Both 
	 * {@link TreeStore} and {@link ListStore} support these. If reorderable 
	 * is TRUE, then the user can reorder the model by dragging and dropping 
	 * rows. The developer can listen to these changes by adding listeners.
	 *
	 * <p>This function does not give you any degree of control over the order 
	 * -- any reorderering is allowed. If more control is needed, you should 
	 *  probably handle drag and drop manually.
	 *
	 * @param reorderable TRUE, if the tree can be reordered.
	 */
	public void setReorderable(boolean reorderable) {
		gtk_tree_view_set_reorderable(getHandle(), reorderable);
	}
	
	public boolean getReorderable() {
		return gtk_tree_view_get_reorderable(getHandle());
	}
	
	/**
	 * Sets the model for a GtkTreeView. 
	 * If the {@link TreeView} already has a model set, 
	 * it will remove it before setting the new model. 
	 * If model is NULL, then it will unset the old model.
	 *
	 * @param model the new model for the {@link TreeView}
	 */
	public void setModel(TreeModel model) {
			gtk_tree_view_set_model(getHandle(), model.getHandle());
	}

	/**
	 * Resizes all columns to their optimal width. Only works after the treeview has been realized.
	 */
	public void autoSizeColumns(){
		gtk_tree_view_columns_autosize( getHandle() );
	}
	  
	 
	/**
	 * Returns an array of all the columns currently in the view
	 */
	public TreeViewColumn[] getColumns(){
		int[] hndls = gtk_tree_view_get_columns(getHandle());
		if (null == hndls)
			return null;
		TreeViewColumn[] columns = new TreeViewColumn[hndls.length];
		for (int i = 0; i < hndls.length; i++) {
			GObject obj = retrieveGObject(hndls[i]);
			if (null != obj)
				columns[i] = (TreeViewColumn)obj;
			else
				columns[i] = new TreeViewColumn(hndls[i]);
		}
		return columns;
	}

	/**
	 * Sets the current keyboard focus to be at path, and selects it. This is 
	 * useful when you want to focus the user's attention on a particular 
	 * row. If column is specified, and 
	 * startEditing is TRUE, then editing should be started in the specified 
	 * cell. If focusCell is also specified, the particular cellRenderer in that
	 * column will get focusThis function is often followed by {@link
	 * Widget#grabFocus()} in order to give keyboard focus to the widget. Please
	 * note that editing can only happen when the widget is realized.
	 *
	 * @since 2.2
	 * 
	 * @param path A TreePath
	 * @param focusColumn A TreeViewColumn, or NULL
	 * @param focusCell A cellrenderer, or null
	 * @param startEditing TRUE if the specified cell should start being edited.
	 */
	public void setCursor(TreePath path, TreeViewColumn focusColumn, CellRenderer focusCell, boolean startEditing) {
		gtk_tree_view_set_cursor_on_cell(getHandle(), path.getHandle(), focusColumn.getHandle(), focusCell.getHandle(), startEditing);
	}

	/**
	 * Expands the row at path. This will also expand all parent rows of path as necessary.
	 *
	 * @since 2.2
	 *
	 * @param path path to a row
	 */
	public void expandToPath( TreePath path ){
		gtk_tree_view_expand_to_path(getHandle(), path.getHandle());
	}

	/**
	 * Does anyone want this type of functionality?
	 * todo: gtk_tree_view_enable_model_drag_dest ()
	 * todo: gtk_tree_view_enable_model_drag_source ()
	 * gtk_tree_view_unset_rows_drag_source ()
	 * gtk_tree_view_unset_rows_drag_dest ()
	 * gtk_tree_view_set_drag_dest_row ()
	 * gtk_tree_view_get_drag_dest_row ()
	 * gtk_tree_view_get_dest_row_at_pos ()
	 * 
	 */

	/**
	 * If enable search is set, then the user can type in text to search through
	 * the tree interactively.
	 * @param enableSearch TRUE, if the user can search interactively
	 */
	public void setEnableSearch(boolean enableSearch) {
		gtk_tree_view_set_enable_search(getHandle(), enableSearch);
	}
	
	public boolean getEnableSearch() {
		return gtk_tree_view_get_enable_search(getHandle());
	}

	/**
	 * Sets column as the column where the interactive search code should 
	 * search in. Additionally, turns on interactive searching.
	 * @param column The column to search in
	 */
	public void setSearchColumn(TreeViewColumn column) {
		gtk_tree_view_set_search_column(getHandle(), column.getHandle());
	}
	
	public TreeViewColumn getSearchColumn() {
		int hndl = gtk_tree_view_get_search_column(getHandle());
		GObject obj = retrieveGObject(hndl);
		if (null != obj)
			return (TreeViewColumn)obj;
		return new TreeViewColumn(hndl);
	}

	/**
	 * Retrieve the runtime type used by the GLib library.
	 */
	public static Type getType() {
		return new Type(gtk_tree_view_get_type());
	}
	

	/***************************************
	 * Event Handler Related code
	 ****************************************/

	/**
	 * Listeners for handling toggle events
	 */
	private Vector listeners = null;
	/**
	 * Register an object to handle button events.
	 * @see org.gnu.gtk.event.TreeViewListener
	 */
	public void addListener(TreeViewListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(listeners, listener);
		if (i == -1) {
			if (null == listeners) {
				listeners = new Vector();
			}
			listeners.addElement(listener);
		}
	}
	/**
	 * Removes a listener
	 * @see #addListener(TreeViewListener)
	 */
	public void removeListener(TreeViewListener listener) {
		int i = findListener(listeners, listener);
		if (i > -1) {
			listeners.remove(i);
		}
		if (0 == listeners.size()) {
			listeners = null;
		}
	}

	/**
	 * Give us a way to locate a specific listener in a Vector.
	 * @param list The Vector of listeners to search.
	 * @param listener The object that is to be located in the Vector.
	 * @return Returns the index of the listener in the Vector, or -1 if
	 *                 the listener is not contained in the Vector.
	 */
	protected static int findListener(Vector list, Object listener) {
		if (null == list || null == listener)
			return -1;
		return list.indexOf(listener);
	}

	protected void fireTreeViewEvent(TreeViewEvent event) {
		if (null == listeners) {
			return;
		}
		int size = listeners.size();
		int i = 0;
		while (i < size) {
			TreeViewListener tl = (TreeViewListener)listeners.elementAt(i);
			tl.treeViewEvent(event);
			i++;
		}
	}

	private void handleRowActivated(int path, int column) {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.ROW_ACTIVATED);
		event.setTreePath(new TreePath(path));
		GObject obj = retrieveGObject(column);
		if (null != obj)
			event.setTreeColumn((TreeViewColumn)obj);
		else
			event.setTreeColumn(new TreeViewColumn(column));
		fireTreeViewEvent(event);
	}

	private void handleRowExpanded(int iter, int path) {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.ROW_EXPANDED);
		event.setTreePath(new TreePath(path));
		event.setTreeIter(new TreeIter(iter, getModel()));
		fireTreeViewEvent(event);
	}

	private void handleRowCollapsed(int iter, int path) {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.ROW_COLLAPSED);
		event.setTreePath(new TreePath(path));
		event.setTreeIter(new TreeIter(iter, getModel()));
		fireTreeViewEvent(event);
	}

	private void handleColumnsChanged() {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.COLUMNS_CHANGED);
		fireTreeViewEvent(event);
	}

	private boolean handleSelectAll() {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.SELECT_ALL);
		fireTreeViewEvent(event);
		return true;
	}

	private boolean handleUnselectAll() {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.UNSELECT_ALL);
		fireTreeViewEvent(event);
		return true;
	}
	
	private boolean handleSelectCursorRow(boolean startEditing) {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.SELECT_CURSOR_ROW);
		event.setStartEditing(startEditing);
		fireTreeViewEvent(event);
		return true;
	}
	
	private boolean handleToggleCursorRow() {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.TOGGLE_CURSOR_ROW);
		fireTreeViewEvent(event);
		return true;
	}
	
	private boolean handleExpandCollapseCursorRow(boolean logical, boolean expand, boolean openAll) {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.EXPAND_COLLAPSE_CURSOR_ROW);
		event.setLogical(logical);
		event.setExpand(expand);
		event.setOpenAll(openAll);
		fireTreeViewEvent(event);
		return true;
	}
	
	private boolean handleSelectCursorParent() {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.SELECT_CURSOR_PARENT);
		fireTreeViewEvent(event);
		return true;
	}

	private boolean handleStartInteractiveSearch() {
		TreeViewEvent event = new TreeViewEvent(this, TreeViewEvent.Type.START_INTERACTIVE_SEARCH);
		fireTreeViewEvent(event);
		return true;
	}

	protected void initializeEventHandlers() {
		if (!eventsInitialized) {
			super.initializeEventHandlers();
			evtMap.initialize(this);
			eventsInitialized = true;
		}
	}

	public Class getEventListenerClass(String signal) {
		Class cls = evtMap.getEventListenerClass(signal);
		if (cls == null) cls = super.getEventListenerClass(signal);
		return cls;
	}

	public GtkEventType getEventType(String signal) {
		GtkEventType et = evtMap.getEventType(signal);
		if (et == null) et = super.getEventType(signal);
		return et;
	}

	private static EventMap evtMap = new EventMap();
	static {
		addEvents(evtMap);
	}

	/**
	* Implementation method to build an EventMap for this widget class.
	* Not useful (or supported) for application use.
	*/
	private static void addEvents(EventMap anEvtMap) {
		anEvtMap.addEvent("row_activated", "handleRowActivated", TreeViewEvent.Type.ROW_ACTIVATED, TreeViewListener.class);
		anEvtMap.addEvent("row_expanded", "handleRowExpanded", TreeViewEvent.Type.ROW_EXPANDED, TreeViewListener.class);
		anEvtMap.addEvent("row_collapsed", "handleRowCollapsed", TreeViewEvent.Type.ROW_COLLAPSED, TreeViewListener.class);
		anEvtMap.addEvent("columns_changed", "handleColumnsChanged", TreeViewEvent.Type.COLUMNS_CHANGED, TreeViewListener.class);
		anEvtMap.addEvent("select_all", "handleSelectAll", TreeViewEvent.Type.SELECT_ALL, TreeViewListener.class);
		anEvtMap.addEvent("unselect_all", "handleUnselectAll", TreeViewEvent.Type.UNSELECT_ALL, TreeViewListener.class);
		anEvtMap.addEvent("select_cursor_row", "handleSelectCursorRow", TreeViewEvent.Type.SELECT_CURSOR_ROW, TreeViewListener.class);
		anEvtMap.addEvent("toggle_cursor_row", "handleToggleCursorRow", TreeViewEvent.Type.TOGGLE_CURSOR_ROW, TreeViewListener.class);
		anEvtMap.addEvent("expand_collapse_cursor_row", "handleExpandCollapseCursorRow", TreeViewEvent.Type.EXPAND_COLLAPSE_CURSOR_ROW, TreeViewListener.class);
		anEvtMap.addEvent("select_cursor_parent", "handleSelectCursorParent", TreeViewEvent.Type.SELECT_CURSOR_PARENT, TreeViewListener.class);
		anEvtMap.addEvent("start_interactive_search", "handleStartInteractiveSearch", TreeViewEvent.Type.START_INTERACTIVE_SEARCH, TreeViewListener.class);
	}


	/****************************************
	 * BEGINNING OF JNI CODE
	 ****************************************/
	native static final protected int gtk_tree_view_get_type();
	native static final protected int gtk_tree_view_new();
	native static final protected int gtk_tree_view_new_with_model(int model);
	native static final protected int gtk_tree_view_get_model(int treeView);
	native static final protected void gtk_tree_view_set_model(int treeView, int model);
	native static final protected int gtk_tree_view_get_selection(int treeView);
	native static final protected int gtk_tree_view_get_hadjustment(int treeView);
	native static final protected void gtk_tree_view_set_hadjustment(int treeView, int adjustment);
	native static final protected int gtk_tree_view_get_vadjustment(int treeView);
	native static final protected void gtk_tree_view_set_vadjustment(int treeView, int adjustment);
	native static final protected boolean gtk_tree_view_get_headers_visible(int treeView);
	native static final protected void gtk_tree_view_set_headers_visible(int treeView, boolean headersVisible);
	native static final protected void gtk_tree_view_columns_autosize(int treeView);
	native static final protected void gtk_tree_view_set_headers_clickable(int treeView, boolean setting);
	native static final protected void gtk_tree_view_set_rules_hint(int treeView, boolean setting);
	native static final protected boolean gtk_tree_view_get_rules_hint(int treeView);
	native static final protected int gtk_tree_view_append_column(int treeView, int column);
	native static final protected int gtk_tree_view_remove_column(int treeView, int column);
	native static final protected int gtk_tree_view_insert_column(int treeView, int column, int position);
	native static final protected int gtk_tree_view_get_column(int treeView, int n);
	native static final protected int[] gtk_tree_view_get_columns(int treeView);
	native static final protected void gtk_tree_view_move_column_after(int treeView, int column, int baseColumn);
	native static final protected void gtk_tree_view_set_expander_column(int treeView, int column);
	native static final protected int gtk_tree_view_get_expander_column(int treeView);
	native static final protected void gtk_tree_view_scroll_to_point(int treeView, int treeX, int treeY);
	native static final protected void gtk_tree_view_scroll_to_cell(int treeView, int path, int column, boolean useAlign, double rowAlign, double colAlign);
	native static final protected void gtk_tree_view_row_activated(int treeView, int path, int column);
	native static final protected void gtk_tree_view_expand_all(int treeView);
	native static final protected void gtk_tree_view_collapse_all(int treeView);
	native static final protected void gtk_tree_view_expand_to_path(int treeView, int path);
	native static final protected boolean gtk_tree_view_expand_row(int treeView, int path, boolean openAll);
	native static final protected boolean gtk_tree_view_collapse_row(int treeView, int path);
	native static final protected boolean gtk_tree_view_row_expanded(int treeView, int path);
	native static final protected void gtk_tree_view_set_reorderable(int treeView, boolean reorderable);
	native static final protected boolean gtk_tree_view_get_reorderable(int treeView);
	native static final protected void gtk_tree_view_set_cursor(int treeView, int path, int focusColumn, boolean startEditing);
	native static final protected void gtk_tree_view_set_cursor_on_cell(int treeView, int path, int focusColumn, int focusCell, boolean startEditin);
	native static final protected void gtk_tree_view_get_cursor(int treeView, int[] path, int[] focusColumn);
//	native static final protected int gtk_tree_view_get_bin_window(int treeView);
//	native static final protected boolean gtk_tree_view_get_path_at_pos(int treeView, int x, int y, int[] path, int[] column, int[] cellX, int[] cellY);
//	native static final protected int gtk_tree_view_get_cell_area(int treeView, int path, int column);
//	native static final protected int gtk_tree_view_get_background_area(int treeView, int path, int column);
//	native static final protected int gtk_tree_view_get_visible_rect(int treeView);
//	native static final protected void gtk_tree_view_widget_to_tree_coords(int treeView, int wx, int wy, int[] tx, int[] ty);
//	native static final protected void gtk_tree_view_tree_to_widget_coords(int treeView, int tx, int ty, int[] wx, int[] wy);
//	native static final protected void gtk_tree_view_enable_model_drag_source(int treeView, int buttonMask, int[] targets, int action);
//	native static final protected void gtk_tree_view_enable_model_drag_dest(int treeView, int[] targets, int action);
//	native static final protected void gtk_tree_view_unset_rows_drag_source(int treeView);
//	native static final protected void gtk_tree_view_unset_rows_drag_dest(int treeView);
//	native static final protected int gtk_tree_view_create_row_drag_icon(int treeView, int path);
	native static final protected void gtk_tree_view_set_enable_search(int treeView, boolean enableSearch);
	native static final protected boolean gtk_tree_view_get_enable_search(int treeView);
	native static final protected int gtk_tree_view_get_search_column(int treeView);
	native static final protected void gtk_tree_view_set_search_column(int treeView, int column);
	/****************************************
	 * END OF JNI CODE
	 ****************************************/
}
