// Copyright 1996, Marimba Inc. All Rights Reserved.


// @(#)TreeWidget.java, 1.22, 12/10/96





package marimba.gui;





import java.awt.*;


import java.util.*;





import marimba.persist.*;





/**


 * A widget for displaying a hierarchical list.


 *


 * @author	Arthur van Hoff


 * @version 	1.22, 12/10/96


 */ 


public class TreeWidget extends ScrollingContainerWidget implements WidgetLayoutMgr {


    public final static Font font1 = new Font("Dialog", Font.PLAIN, 12);


    public final static Font font2 = new Font("Dialog", Font.ITALIC, 12);





    /**


     * The root can be shown or hidden by the tree.


     * @see #getShowRoot


     * @see #setShowRoot


     */


    public boolean showRoot = true;





    /**


     * The treeWidget needs to get the focus once, to select its


     * first item. After that the items receive the focus, so then


     * the treeWidget is not interested in the focus anymore.


     * @see #focusInterest


     */


    boolean  hadFocus = false;





    /** the label of the root for 'showRoot' */


    String  rootLabel = "Root";








    /**


     * Constructor.


     */


    public TreeWidget() {


    }





    /**


     * Get the properties of this widget.


     */


    public void getProperties(PropertyList list) {


	super.getProperties(list);


	list.setBoolean("showRoot", showRoot, true);


    }





    /**


     * Set the properties of this widget.


     */


    public void setProperties(PropertyList list) {


	super.setProperties(list);


	setShowRoot(list.getBoolean("showRoot", true));


    }





    /**


     * Check whether the tree shows the root.


     * @see #showRoot


     */


    public boolean getShowRoot() {


	return showRoot;


    }





    /**


     * Show or hide the root.


     * @see #showRoot


     */


    public void setShowRoot(boolean showRoot) {


	if (showRoot != this.showRoot) {


	    TreeNodeWidget  root = getRoot();


	    if (root != null) {


		if (showRoot) {


		    root.label = rootLabel;


		    root.layout();


		} else {


		    rootLabel = root.label;


		    root.label = null;


		    root.layout();


		}


	    }


	    this.showRoot = showRoot;


	}


    }





    /**


     * Allocate the content.


     */


    public Widget newContent() {


	GroupWidget w = new GroupWidget();


	w.lineMode = LOWERED;


	w.layoutMgr = this;


	return w;


    }





    /**


     * Layout the content


     */


    public void layout(Widget w) {


	if (w.nwidgets == 0) {


	    setContentSize(0, 0);


	    return;


	}





	int y = 4, width = 0;


	for (int i = 0 ; i < w.nwidgets ; i++) {


	    Widget item = w.widgets[i];


	    item.move(4, y);


	    item.validate();


	    y += item.height;


	    width = Math.max(item.width, width);


	}


	setContentSize(width + 8, y + 4);


    }





    /**


     * Collapse all.


     */


    public void expandAll() {


	collapseAll(false);


    }





    /**


     * Collapse all.


     */


    public void collapseAll() {


	collapseAll(true);


    }





    /**


     * Collapse all


     */


    public void collapseAll(boolean collapsed) {


	for (int i = content.nwidgets ; i-- > 0 ;) {


	    if (content.widgets[i] instanceof TreeNodeWidget) {


		((TreeNodeWidget)content.widgets[i]).collapseAll(collapsed);


	    }


	}


    }





    /**


     * Get the rood node of this tree.


     * Returns null if none is found.


     */


    public TreeNodeWidget getRoot() {


	TreeNodeWidget  result = null;


	for (int i = content.nwidgets ; i-- > 0 ;) {


	    if (content.widgets[i] instanceof TreeNodeWidget) {


		result = (TreeNodeWidget)content.widgets[i];


		while (result.parent instanceof TreeNodeWidget) {


		    result = (TreeNodeWidget)result.parent;


		}


		break;


	    }


	}


	return result;


    }





    /**


     * Get the selected Tree node.


     */


    public TreeNodeWidget getSelected() {


	for (int i = content.nwidgets ; i-- > 0 ;) {


	    if (content.widgets[i] instanceof TreeNodeWidget) {


		TreeNodeWidget node = (TreeNodeWidget)content.widgets[i];


		TreeNodeWidget sel = node.getSelected();


		if (sel != null) {


		    return sel;


		}


	    }


	}


	return null;


    }





    /**


     * Focus on a TreeNodeWidget.


     */


    public void focus(TreeNodeWidget node) {


	int x = node.x;


	int y = node.y;


	for (Widget w =  node.parent ; w != content ; w = w.parent) {


	    x += w.x + w.tx;


	    y += w.y + w.ty;


	}


	if (horzmode == NEVER) {


	    x = 0;


	}


	focusContent(x, y, node.width, 30);


    }





    /**


     * Return a vector of nodes that are visible, in linear order.


     */


    public Vector getNodes() {


	Vector v = new Vector();


	for (int i = 0 ; i < content.nwidgets ; i++) {


	    Widget node = content.widgets[i];


	    if ((node instanceof TreeNodeWidget) && node.isVisible()) {


		((TreeNodeWidget)node).getNodes(v);


	    }


	}


	return v;


    }





    /**


     * Return a vector of all nodes, in linear order.


     */


    public Vector getAllNodes() {


	Vector v = new Vector();


	for (int i = 0 ; i < content.nwidgets ; i++) {


	    Widget node = content.widgets[i];


	    if (node instanceof TreeNodeWidget) {


		((TreeNodeWidget)node).getAllNodes(v);


	    }


	}


	return v;


    }





    /**


     * Add a tree node.


     */


    public void add(TreeNodeWidget node) {


	node.setTreeWidget(this);


	content.add(node);


    }





    /**


     * Make the tree empty again: remove all nodes.


     */


    public void clear() {


	for (int i = content.nwidgets ; i-- > 0 ;) {


	    Widget node = content.widgets[i];


	    if (node instanceof TreeNodeWidget) {


		content.remove(node);


	    }


	}


    }





    /**


     * Handle the GOT_FOCUS event.


     */


    public boolean handleEvent(Event evt) {


	switch (evt.id) {


	    case Event.GOT_FOCUS:


		hadFocus = true;


		TreeNodeWidget  firstNode = null;


		for (int i = 0; i < content.nwidgets; i++) {


		    Widget node = content.widgets[i];


		    if (node instanceof TreeNodeWidget && node.isVisible()) {


			firstNode = (TreeNodeWidget) node;


			break;


		    }


		}


		if (firstNode != null) {


		    firstNode.focus();


		    firstNode.select();


		    firstNode.requestFocus();


		}


		return true;


	}


	return super.handleEvent(evt);


    }





    /**


     * A tree is interested in the focus if no node is selected yet.


     * @see #hadFocus


     */


    public boolean focusInterest() {


	return (hadFocus) ? false : getSelected()==null;


    }


}


