package org.gnu.gtk;

import org.gnu.glib.Boxed;
import org.gnu.glib.Handle;

/**
 * A TreeRowReference behaves similar to a {@see org.gnu.gtk.TreeIter} in that
 * it is a reference to a node in a {@see javax.swing.tree.TreeModel}. With a
 * TreeRowReference however you don't need to worry about it becoming
 * invalidated when the underlying model changes. TreeRowReferences listen to
 * signals emitted by the model and modifies their state accordingly.<br>
 * 
 * <p>
 * To create a TreeRowReference you need a reference to a
 * {@see org.gnu.gtk.TreeModel} and a {@see org.gnu.gtk.TreePath}:<br>
 * 
 * <pre>
 * TreeRowReference ref = new TreeRowReference(model, path)
 * </pre>
 * 
 * <br>
 * You can then accesss the model and path stored in the reference by using<br>
 * 
 * <pre>
 * TreeModel model = ref.getModel();
 * </pre>
 * 
 * <br>
 * 
 * <pre>
 * TreePath path = ref.getPath();
 * </pre>
 * 
 * <br>
 * </p>
 * 
 * <p>
 * TreeRowReferences can become invalidated if the node they are pointing to no
 * longer exists, you should check for this by using
 * 
 * <pre>
 * ref.isValid()
 * </pre>
 * 
 * </p>
 * 
 */
public class TreeRowReference extends Boxed {

	/**
	 * Creates a row reference based on path. This reference will keep pointing
	 * to the node pointed to by path, so long as it exists. It listens to all
	 * signals emitted by model, and updates its path appropriately. If path
	 * isn't a valid path in model, an IllegalArgumentException is thrown.
	 * 
	 * @param model
	 *            The model the reference will use
	 * @param path
	 *            Valid TreePath to the node to keep a reference to
	 */
	public TreeRowReference(TreeModel model, TreePath path)
			throws IllegalArgumentException {
		super(init(model, path));
	}

	private static Handle init(TreeModel model, TreePath path) {
		Handle hndl = gtk_tree_row_reference_new(model.getHandle(), path
				.getHandle());
		if (hndl == null)
			throw new IllegalArgumentException("Invalid treepath");

		return hndl;
	}

	/**
	 * @return the model which reference is monitoring in order to appropriately
	 *         modify the path.
	 */
	public TreeModel getModel() {
		return TreeModel.getTreeModel(gtk_tree_row_reference_get_model(this
				.getHandle()));
	}

	/**
	 * @return Returns a path that the row reference currently points to, or
	 *         NULL if the path pointed to is no longer valid.
	 */
	public TreePath getPath() {
		return TreePath.getTreePath(gtk_tree_row_reference_get_path(this
				.getHandle()));
	}

	/**
	 * @return TRUE if the reference refers to a current valid path.
	 */
	public boolean isValid() {
		return gtk_tree_row_reference_valid(this.getHandle());
	}

	protected native static final Handle gtk_tree_row_reference_new(
			Handle model, Handle path);

	protected native static final Handle gtk_tree_row_reference_get_model(
			Handle reference);

	protected native static final Handle gtk_tree_row_reference_get_path(
			Handle reference);

	protected native static final boolean gtk_tree_row_reference_valid(
			Handle reference);
}
