/*
 * 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 org.gnu.glib.Boxed;
import org.gnu.glib.Handle;

/**
 * A path refers to a single row in a {@link TreeModel} (such as a
 * {@link ListStore} or a {@link TreeStore}). In this respect, it is similar to
 * a {@link TreeIter}, however a path also contains details of the structure of
 * the tree (TreeIter is a generic object for the entire TreeView family,
 * including flat lists and tables.)
 */
public class TreePath extends Boxed {
    /**
     * Construct path from native handle
     */
    protected TreePath(Handle handle) {
        super(handle);
    }

    /**
     * Internal static factory method to be used by Java-Gnome only.
     */
    protected static TreePath getTreePath(Handle handle) {
        if (handle == null) {
            return null;
        }
        TreePath treePath = (TreePath) Boxed.getBoxedFromHandle(handle);
        if (treePath == null)
            treePath = new TreePath(handle);

        return treePath;
    }

    /**
     * Constructs a new path.
     */
    public TreePath() {
        super(gtk_tree_path_new());
    }

    /**
     * Creates a new TreePath initialized to <code>path</code>.
     * <code>path</code> is expected to be a colon separated list of numbers.
     * For example, the string "10:4:0" would create a path of depth 3 pointing
     * to the 11th child of the root node, the 5th child of that 11th child, and
     * the 1st child of that 5th child. If an invalid path string is passed in,
     * NULL is returned. TODO: throw an exception on null response.
     */
    public TreePath(String path) {
        super(gtk_tree_path_new_from_string(path));
    }

    /**
     * Generates a string representation of the path. This string is a ':'
     * separated list of numbers. For example, "4:10:0:3" would be an acceptable
     * return value for this string.
     * 
     * @return String representation of the path.
     */
    public String toString() {
        return gtk_tree_path_to_string(getHandle());
    }

    /**
     * Returns the current depth of path.
     */
    public int getDepth() {
        return gtk_tree_path_get_depth(getHandle());
    }

    /**
     * TODO: gtk_tree_path_get_indices ()
     */

    /**
     * Compares the path with another path. If the other path appears before
     * this one in a tree, then -1 is returned. If this one appears before the
     * other, then 1 is returned. If the two nodes are equal, then 0 is
     * returned.
     */
    public int compare(TreePath other) {
        return gtk_tree_path_compare(other.getHandle(), getHandle());
    }

    /**
     * Moves the path to point to the next node at the current depth.
     */
    public void next() {
        gtk_tree_path_next(getHandle());
    }

    /**
     * Moves the path to point to the previous node at the current depth, if it
     * exists.
     * 
     * @return TRUE if path has a previous node, and the move was made.
     */
    public boolean previous() {
        return gtk_tree_path_prev(getHandle());
    }

    /**
     * Moves the path to point to it's parent node, if it has a parent.
     * 
     * @return TRUE if path has a parent, and the move was made.
     */
    public boolean up() {
        return gtk_tree_path_up(getHandle());
    }

    /**
     * Moves path to point to the first child of the current path.
     */
    public void down() {
        gtk_tree_path_down(getHandle());
    }

    /**
     * Returns TRUE if descendant is a descendant of path.
     * 
     * @param descendant
     *            Another TreePath
     * @return TRUE if descendant is contained inside path
     */
    public boolean isAncestor(TreePath descendant) {
        return gtk_tree_path_is_ancestor(getHandle(), descendant.getHandle());
    }

    /**
     * Returns TRUE if path is a descendant of ancestor.
     * 
     * @param ancestor
     *            Another TreePath
     * @return TRUE if ancestor contains path somewhere below it
     */
    public boolean isDescendant(TreePath ancestor) {
        return gtk_tree_path_is_descendant(getHandle(), ancestor.getHandle());
    }

    /**
     * Appends a new index to the path. As a result, the depth of the path is
     * increased
     * 
     * @param index
     */
    public void appendIndex(int index) {
        gtk_tree_path_append_index(getHandle(), index);
    }

    /**
     * Prepends a new index to the path. As a result, the depth of the path is
     * increased
     * 
     * @param index
     */
    public void prependIndex(int index) {
        gtk_tree_path_prepend_index(getHandle(), index);
    }

    /**
     * Returns the current indices of the path.
     * 
     * @return An array of ints, each representing a node in the tree.
     */
    public int[] getIndices() {
        return gtk_tree_path_get_indices(getHandle());
    }

    native static final protected Handle gtk_tree_path_new();

    native static final protected Handle gtk_tree_path_new_from_string(
            String path);

    native static final protected String gtk_tree_path_to_string(Handle path);

    native static final protected Handle gtk_tree_path_new_first();

    native static final protected void gtk_tree_path_append_index(Handle path,
            int index);

    native static final protected void gtk_tree_path_prepend_index(Handle path,
            int index);

    native static final protected int gtk_tree_path_get_depth(Handle path);

    native static final protected int[] gtk_tree_path_get_indices(Handle path);

    native static final protected int gtk_tree_path_compare(Handle a, Handle b);

    native static final protected void gtk_tree_path_next(Handle path);

    native static final protected boolean gtk_tree_path_prev(Handle path);

    native static final protected boolean gtk_tree_path_up(Handle path);

    native static final protected void gtk_tree_path_down(Handle path);

    native static final protected boolean gtk_tree_path_is_ancestor(
            Handle path, Handle descendant);

    native static final protected boolean gtk_tree_path_is_descendant(
            Handle path, Handle ancestor);
}
