/* Proto.H: nodes defined through the PROTO or EXTERNPROTO mechanism */

#ifndef _PROTO_H_
#define _PROTO_H_

#include "xrml.H"
#include "Assoc.H"
#include "CmpString.H"

namespace xrml {

typedef assoc<class comparable_string, class SFNode*> namedNodeTable;
typedef assoc<class comparable_string, class Proto*> protoTable;

class Proto: public SFNode {

protected:
  SFNode *master;		// contains interface of the PROTO node
  virtual void clone(const SFNode& src);
  void clone_interface(const SFNode& src);
  virtual void destruct(void);

  // constructs a Proto node with master 'm', scene graph 'sg' and named nodes 
  // table 'nn'.
  void Proto_construct(SFNode *m, MFNode *sg, const namedNodeTable& nn, const protoTable& pts);

  // instantiates PROTO implementation from master to 'this'
  void instantiate_implementation(Proto* master);

public:
  PoolDecl(Proto, "Proto")
  MFNode *sceneGraph;		// IS-statements link interface member of the nodes
                                // in this sceneGraph to the interface members of the
                                // master node.
  namedNodeTable namedNodes; 	// DEF'ed nodes in PROTO implementation
  protoTable protos;  // PROTO's and EXTERNPROTO's in PROTO implementation

  Proto* parent;           // if non-null, 'this' is an instance of 'parent'

  inline Proto(void) { }
  Proto(SFNode *m, MFNode *sg, const namedNodeTable& nn, const protoTable& pts);
  Proto(const Proto&);
  Proto& operator=(const Proto&);
  ~Proto();

  // Returns first node of PROTO scene graph (determines where
  // PROTO node can be used).
  SFNode *firstnode(void);

  SFNode *instantiate(Proto *enclosing_proto =0);
  void render(void);

  ostream& print(ostream& s =cout);
};

extern bool IsProto(SFNode *node);

} // namespace xrml

#endif /*_PROTO_H_*/
