import netscape_beta.application.*;
import netscape_beta.util.*;

/**
 * A class that displays a node in a class dictionary graph.
 *
 * @version        1.0 12 Dec 1996
 * @author         Andrew Miller
 */
public class TreeNode extends Drawable implements VisitorHost, DragSource, DragDestination, Target
{
  private static String cmdStartNode = new String("cmdTraversalStartNode");
  private static String cmdBypassNode = new String("cmdTraversalBypassNode");
  private static String cmdThroughNode = new String("cmdTraversalThroughNode");
  private static String cmdEndNode = new String("cmdTraversalEndNode");

  protected static String dataType  = new String("TreeNode");
  static private DemDoc m_doc       = null;

  private DragSession drag          = null;
  private int downX                 = 0;
  private int downY                 = 0;
  private Color m_colorPrevious     = colorNormal;
  public boolean m_bInitialized     = false;
  
    /** Returns run-time type information describing the 
      * object type.
      *
      * @return Always "TreeNode"
      */
  public static String dataType()
  {
	 return dataType;
  }

    /** Set the document for which to draw nodes.
      *
      * @param doc  Document being displayed.
      */
  static public void setDoc(DemDoc doc)
  {
      m_doc = doc;
  }

    /** Deault constructor.
      *
      */
  public TreeNode() 
  {
    super();
  }

    /** Initialize and display a TreeNode.
      * @param x            The left position for the node
      * @param y            The top position for the node
      * @param nodename     The label to display for this node
      * @param parent       The view to display the node in.
      */
  public void init(int x, int y, String nodename, View parent)
  {
     super.init(x,y,nodename,parent);
     
     drag = null;
     downX = 0;
     downY = 0;
     m_colorPrevious = colorNormal;
     m_doc = null;

     // currently, TreeNodes may be initialized multiple times
     if(m_bInitialized != true)
         setupProperties();

     m_bInitialized = true;
  }

    /** Initialize the TreeNode's properties.
      */
  private void setupProperties()
  {
//       addProperty("Start Node", cmdStartNode);
       addProperty("Bypass Node", cmdBypassNode);
       addProperty("Through Node", cmdThroughNode);
       addProperty("End Node", cmdEndNode);
  }

    /** Handle a mouse down.  If the user single-clicks
      * a TreeNode, it is added to the active visitor's
      * active traversal.
      * @param event    Mouse event
      */
  public boolean mouseDown(MouseEvent event)
  {
     downX = event.x;
     downY = event.y;

     if (super.mouseDown(event) == false)
     {
         if(event.clickCount() == 2)
         {
             doThroughNode();
         }
     }

     return true;
  }

    /** Host a visitor
      * @param ds   Drag session.
      * @return     true - if visitor dropped
      */
  public boolean dragDropped(DragSession ds)
  {
     Visitor visitor = (Visitor)ds.data();
     
     // make the node look like the visitor
     // setBackgroundColor(visitor.backgroundColor());

     // start a new traversal for this visitor at this node
     visitor.addTraversal(this);
     visitor.showHosts(superview(), true); // superview() == classview

     return true;
  }
  
    /** Determine if we host an object.
      * If a visitor is dragged, temporarily change
      * the TreeNode's background color to that of the
      * visitor to let the user know they've moved
      * across a host.
      * @param ds DragSession
      * return true - if visitor dragged
      */
  public boolean dragEntered(DragSession ds)
  {
      if(Visitor.dataType().equals(ds.dataType()))
      {
         Visitor visitor = (Visitor)ds.data();
     
         // make the node look like the visitor
         m_colorPrevious = backgroundColor();
         setBackgroundColor(visitor.backgroundColor());
         //setBackgroundColor(this.colorHighlight);
         return true;
      }
      else
      {
           return false;
      }
  }

    /** Determine if we host an object.
      * @param ds DragSession
      * @param x  x pos
      * @param y  y pos
      * return true - if visitor dragged
      */
  public DragDestination acceptsDrag(DragSession session, int x, int y) {
        // If an icon is being dragged to us, return the DragDestination
        // (the RootNode itself.)
        if (Visitor.dataType().equals(session.dataType())) {
            return this;
        } else {
            return null;
        }
    }
  
    /** Reset the TreeNode's background color after
      * something is dragged across it.
      * @param ds DragSession
      */
  public void dragExited(DragSession ds)
  {
     setBackgroundColor(m_colorPrevious);
  }
  
    /** Determine if we host an object.
      * @param ds DragSession
      * return true - if visitor dragged
      */
  public boolean dragMoved(DragSession ds)
  {
      if(ds.dataType() == Visitor.dataType())
      {
           return true;
      }
      else
      {
          return false;
      }
  }

    /** Begin a drag and drop session.  Display
      * the visitor image while we move.
      * @param event  Mouse event.
      */
  public void mouseDragged(MouseEvent event)
  {
       if(drag != null)
            return;

       Bitmap bmp = Bitmap.bitmapNamed(new String("treenode.gif"), true);
       drag = new DragSession(this, bmp,
                            0, 0,
                            downX, downY,
                            dataType, this);

  }

    /** End a drag session.
      * @param ds Drag session.
      */
  public void dragWasAccepted(DragSession ds)
  {
     drag = null;
  }

    /** End a drag session.
      * @param ds Drag session.
      */
  public boolean dragWasRejected(DragSession ds)
  {
     drag = null;
     return true; // animate back to original pos    
  }
    
  public boolean wantsMouseTrackingEvents() {
     return true;
  }

  public View sourceView(DragSession session) {
     return this;
  }

  
    /** Host the provided visitor.  Make the TreeNode
      * look like the visitor to represent hosting.
      */
  public void host(Visitor visitor)
  {
      if(visitor == null)
      {
        setBackgroundColor(colorNormal);
      }
      else
      {
        setBackgroundColor(visitor.backgroundColor());
      }

      setDirty(true);
  }

    /** Return the type of this VisitorHost implementor at run-time.
      *
      * @return always "TreeNode"
      */
  public String hostType()
  {
      return dataType();
  }

    /** Return the node name to be used when generating
      * the traversal behavior.
      * 
      * @return node name.
      */
  public String getNameForTraversal()
  {
     return getNodeName();
  }
 
    /** Respond to a command generated by the TreeNode's
      * property menu
      * @param string   Command string
      * @param obj      Object generating command
      */
  public void performCommand(String string, Object obj)
  {
      super.performCommand(string, obj);

      if(string.equals(cmdStartNode))
      {
          doStartNode();
      }
      else if(string.equals(cmdBypassNode))
      {
          doBypassNode();
      }
      else if(string.equals(cmdThroughNode))
      {
          doThroughNode();
      }
      else if(string.equals(cmdEndNode))
      {
          doEndNode();
      }
  }

    /** NOT IMPLEMENTED */
  protected void doStartNode()
  {
     // NOT IMPLEMENTED
  }

    /** Add the TreeNode to the active visitor's active traversal
      * as a bypass node
      */
  protected void doBypassNode()
  {
     // LoD violation here
     Visitor visitor = m_doc.get_visitorManager().get_active();

     if(visitor != null)
     {
        visitor.updateCurrentTraversal(this, Visitor.BYPASS);
        visitor.showHosts(superview(), true);
     }
  }

    /** Add the TreeNode to the active visitor's active traversal
      * as a through node
      */
  protected void doThroughNode()
  {
     // LoD violation here
     Visitor visitor = m_doc.get_visitorManager().get_active();

     if(visitor != null)
     {
        visitor.updateCurrentTraversal(this, Visitor.THROUGH);
        visitor.showHosts(superview(), true);
     }
  }

    /** Add the TreeNode to the active visitor's active traversal
      * as an end node
      */
  protected void doEndNode()
  {
     // LoD violation here
     Visitor visitor = m_doc.get_visitorManager().get_active();

     if(visitor != null)
     {
        visitor.updateCurrentTraversal(this, Visitor.END);
        visitor.showHosts(superview(), true);
     }
  }

}


