/*  
 *    SCCS ID: %Z%%M% %I% %E% SST
 *
 *    Copyright (c) 1992-1993 Mark Soloway.  All rights reserved.
 *    See SST_LEGAL_NOTICE file for terms of the license. 
 */  
  
#include "CanvasShellDisplay.h"
#include "CSDrawIcon.h"
#include "CSTree.h"
#include "TreeNode.h"
#include "TTMessage.h"
#include "TreeDisplayer.h"
#include "TreeManagerGetRootMessage.h"

char *TreeDisplayer::selectedNodeID;

Tt_status TreeDisplayer::defaultSessionCallback (TTMessage* message)
{
  Tt_status  status;
  char      *child_objid = (char *)NULL;
  char      *parent_objid = (char *)NULL;
  char      *op = message->getOp (status);

  if (status == TT_OK) {
    canvas_shell->setDelayRepaint (TRUE);

    if (!strcmp (op, TREE_DISPLAYER_OP_CHILD_ADDED)) {
      status = message->getArgValue (1, child_objid);

      if (child_objid && (status == TT_OK)) {
	status = message->getArgValue (0, parent_objid);

	if (status == TT_OK) {
	  TreeNode child (child_objid, status);

	  CSDrawIcon *child_icon;
	  if (status < TT_WRN_LAST) {
	    child_icon = child.getIcon (status);

	    // In some versions of ToolTalk there is a bug that causes
	    // 2 file-scoped notices to be received instead of 1.
	    // If the child icon already has a parent, then it is already
	    // displayed and there is no need to add it to the tree.
            if (!child_icon->getParent () && (status < TT_WRN_LAST)) {
	      if (parent_objid) {
	        // Adding child to root
	        if (*root == parent_objid) {
		  CSDrawIcon *root_icon = root->getIcon (status);

		  if (root_icon && (status < TT_WRN_LAST)) {
		    tree->addLink (*root_icon, *child_icon);
		  }
	        }
	        // Adding child to regular node
	        else {
		  TreeNode parent (parent_objid, status);

		  CSDrawIcon *parent_icon = (CSDrawIcon *)NULL;
		  if (status < TT_WRN_LAST) {
		    parent_icon = parent.getIcon (status);
		  }

		  if (parent_icon && (status < TT_WRN_LAST)) {
		    tree->addLink (*parent_icon, *child_icon);
		  }
	        }
	      }
	    }
	  }
	}
      }
    }
    else if (!strcmp (op, TREE_DISPLAYER_OP_REFRESH_TREE)) {
      status = displayTree ();
    }

    canvas_shell->setDelayRepaint (FALSE);
  }

  return status;
}

Tt_status TreeDisplayer::displayTree ()
{
  Tt_status  status;

  if (root) {
    delete root;
    tree->setSelectedNodeID ((char *)NULL);
  }

  TreeManagerGetRootMessage message (status);
  TTSession                 temp_session = *this;
  if (status == TT_OK) {
    status = temp_session.sendSynchronousMessage (message);
  }

  if (status == TT_OK) {
    root = new TreeNode (message.getRootID (status), status);

    if (status < TT_WRN_LAST) {
      CSDrawIcon *root_icon = root->getIcon (status);

      if (root_icon && (status == TT_OK)) {
        tree->addLink (*tree, *root_icon);

        if (status < TT_WRN_LAST) {
	  if (status < TT_WRN_LAST) {
            TreeNodeArray *children = root->getChildren (status);

            if (children && (status < TT_WRN_LAST)) {
              status = addChildren (root, children);
	      delete children;
            }
	  }
        }
      }
    }
  }

  return status;
}

Tt_status TreeDisplayer::addChildren (TreeNode      *parent_node,
				      TreeNodeArray *children)
{
  Tt_status   status;
  CSDrawIcon *parent_icon = parent_node->getIcon (status);

  int num_children = children->getSize ();
  for (int i=0; (i < num_children) && (status < TT_WRN_LAST); i++) {
    CSDrawIcon *child_icon = (*children) [i]->getIcon (status);

    if (child_icon && (status < TT_WRN_LAST)) {
      tree->addLink (*parent_icon, *child_icon);
    }

    if (status < TT_WRN_LAST) {
      if (status < TT_WRN_LAST) {
        TreeNodeArray *grand_children = (*children) [i]->getChildren (status);

        if (grand_children && (status < TT_WRN_LAST)) {
          status = addChildren ((*children) [i], grand_children);
	  delete grand_children;
        }
      }
    }
  }

  return status;
}
