Image

Imagebanana wrote in Imagejava_dev 🤓geeky

Listens: Take Me To A Distant Ba... [SomaFM]

Drawing a tree

I had to replicate a Swing app with JSP, and it had a tree in the manner of the Windows Explorer. It turned out not to be too hard to draw a tree just as text. If you think that sounds interesting, here's my tree drawing test class.


You can fiddle with the tree construction in main if you're really bored. ;~)


import java.util.Vector;

/**
 * Represents tree holding objects.
 * Draws tree as characters.
 */
public class Tree
{
	/**
	 * Constructs an arbitrary tree to test drawing.
	 */
	public static void main ( String [] args )
	{
		System.out.println ( "Creating root..." );
		Tree root = new Tree ( "root" );

		System.out.println ( "Adding branches..." );
		Tree branch1 = new Tree ( "branch 1" );
		Tree branch2 = new Tree ( "branch 2" );
		root.add ( branch1 );
		root.add ( branch2 );

		System.out.println ( "Adding a leaf..." );
		Tree leaf1 = new Tree ( "leaf 1" );
		branch1.add ( leaf1 );

		System.out.println ( "Adding sub-branches..." );
		Tree subBranch1 = new Tree ( "sub-branch 1" );
		Tree subBranch2 = new Tree ( "sub-branch 2" );
		branch1.add ( subBranch1 );
		branch1.add ( subBranch2 );

		System.out.println ( "Adding more leaves..." );
		Tree leaf2 = new Tree ( "leaf 2" );
		Tree leaf3 = new Tree ( "leaf 3" );
		Tree leaf4 = new Tree ( "leaf 4" );
		Tree leaf5 = new Tree ( "leaf 5" );
		Tree leaf6 = new Tree ( "leaf 6" );
		Tree leaf7 = new Tree ( "leaf 7" );
		Tree leaf8 = new Tree ( "leaf 8" );
		subBranch1.add ( leaf2 );
		subBranch1.add ( leaf3 );
		subBranch2.add ( leaf4 );
		branch1.add ( leaf6 );
		branch2.add ( leaf7 );
		branch2.add ( leaf8 );

		System.out.println ( "Drawing tree..." );
		System.out.println ();
		root.draw ();
		System.out.println ();
		System.out.println ();
		System.out.println ( "Drawing sub-tree..." );
		System.out.println ();
		branch2.draw ();
		System.out.println ();
		System.out.println ();
		System.out.println ( "Drawing silly sub-tree to make sure it works..." );
		System.out.println ();
		leaf8.draw ();
		System.out.println ();
	}

	public static final int NOT_DRAWING        = 0;
	public static final int DRAWING            = 1;
	public static final int DRAWING_LAST_CHILD = 2;

	private Object  node;
	private Vector  branches    = new Vector ();
	private int     drawStatus  = NOT_DRAWING;
	private Tree    parent;

	/**
	 * Constructs with the useful content of this tree element.
	 *
	 * @param s  any object you like, even null,
	 *           but bear in mind that the toString()
	 *           output of this object is used to display this element
	 *           in drawing the tree
	 */
	public Tree ( Object s )
	{
		node = s;
	}

	/**
	 * Adds a tree element as a child of this element.
	 */
	public synchronized void add ( Tree t )
	{
		branches.add ( t );
		t.setParent ( this );
	}

	public int getDrawStatus ()
	{
		return drawStatus;
	}

	protected void setParent ( Tree t )
	{
		parent = t;
	}

	public Tree getParent ()
	{
		return parent;
	}

	public void draw ()
	{
		draw ( 0 );
	}

	protected synchronized void draw ( int indent )
	{
		StringBuffer tabs1       = new StringBuffer ();
		StringBuffer tabs2       = new StringBuffer ();
		int          branchCount = branches.size ();

		drawStatus = DRAWING;
		if ( branchCount != 0 )
		{
			tabs2.append ( "+-" );
		}

		Tree nextParent = getParent();
		for ( int i = 0; i < indent && parent != null; i++ )
		{
			if ( i == 0 )
			{
				tabs2.insert ( 0, "+--" );
				tabs1.insert ( 0, "|  " );
			}
			else if ( nextParent.getDrawStatus () == DRAWING_LAST_CHILD )
			{
				tabs2.insert ( 0, "   " );
				tabs1.insert ( 0, "   " );
			}
			else
			{
				tabs2.insert ( 0, "|  " );
				tabs1.insert ( 0, "|  " );
			}
			nextParent = nextParent.getParent ();
		}
		tabs2.append ( ' ' );

		if ( indent > 0 )
		{
			System.out.println ( tabs1 );
		}
		System.out.print ( tabs2 );
		System.out.println ( node );

		Tree [] branchArray = new Tree [ branchCount ];
		branches.toArray ( branchArray );
		for ( int i = 0; i < branchArray.length; i++ )
		{
			if ( i + 1 == branchArray.length )
			{
				drawStatus = DRAWING_LAST_CHILD;
			}
			branchArray [ i ].draw ( indent + 1 );
		}

		drawStatus = NOT_DRAWING;
	}
}