/*
 ******************************************************************************
 *
 *	ParcPlace Systems, Inc.
 *	Copyright (c) 1990, ParcPlace Systems, Inc. USA   All rights reserved.
 *
 ****************************************************************************
 *
 *	File:	Plmtree.H
 *
 *	Functions(s):
 *
 *	Description:
 *		Private OI_layout_tree_* class header
 *		Adapted from "Drawing Dynamic Trees, Sven Moen, Brown University, IEEE Software, July 1990
 *
 *	RCSid = "$Id: Plmtree.H,v 1.1.1.1 1993/06/01 22:52:05 mth Exp $"
 *
 ****************************************************************************
 */

#ifndef OI_Plmtree_H
#define OI_Plmtree_H

		class	OI_lm_polyline ;
		class	OI_lm_polygon ;
		class	OI_lm_boundary ;
		class	OI_lm_tree ;

		class	OI_lm_polyline	{
			OI_xy			delta ;						/* change in x, y assuming line starts at 0,0 */
			OI_lm_polyline		*lnk ;						/* ptr to next segment in polyline */
		 public:
						OI_lm_polyline(OI_number dx, OI_number dy, OI_lm_polyline *p) ;
						~OI_lm_polyline() ;
			OI_lm_polyline		*bridge(int,int,OI_lm_polyline*,int,int) ;
			OI_lm_polyline		*copy() ;					/* copy complete polyline chain */
			OI_number		delta_x() const			{ return(delta.x); }
			OI_number		delta_y() const			{ return(delta.y); }
			OI_lm_polyline		*extract_next()			{ OI_lm_polyline *p=lnk; lnk=NULL; return(p); }
			OI_lm_polyline		*next() const			{ return(lnk); }
			void			set_next(OI_lm_polyline *p) ;
			OI_lm_polyline		*tail() const ;					/* get ptr to last segment in line */
		} ;

		class	OI_lm_boundary {							/* polyline bounding a polygon */
			OI_lm_polyline		*hdp ;						/* ptr to first segment of line boundary */
			OI_lm_polyline		*tlp ;						/* ptr to last segment of line boundary */
		 public:
						OI_lm_boundary()		{ hdp=tlp=NULL; }
			void			clear()				{ if (hdp) delete hdp ; hdp=tlp=NULL; }
			void			copy(OI_lm_boundary *p) ;
			OI_lm_polyline		*extract_head()			{ OI_lm_polyline *p=hdp; hdp=NULL; return(p); }
			OI_lm_polyline		*head() const			{ return(hdp); }
			void			set_head(OI_lm_polyline *p) ;
			void			set_tail(OI_lm_polyline *p) ;
			OI_lm_polyline		*tail() const			{ return(tlp); }
		} ;

		class	OI_lm_polygon	{
			OI_lm_boundary		upr ;						/* polyline describing upper bound */
			OI_lm_boundary		lwr ;						/* polyline describing lower bound */
		 public:
			OI_lm_boundary		*upper() const			{ return((OI_lm_boundary*)&upr); }
			OI_lm_boundary		*lower() const			{ return((OI_lm_boundary*)&lwr); }
		} ;

		class	OI_lm_tree_node : public OI_lm_obj_box {
						// nxt points to sibling
						// prv is predecessor sibling; NULL if this is first child
						// hdrp points to parent
						// slotp points to child
						// psn is pos
						// strtch unused
						// siz is width and height
						// val unused
				OI_xy		off ;						/* offset of node from its predecessor */
												/* predecessor is the unique node which points to this node */
				OI_lm_polygon	cntr ;						/* coutour of this node */
				OI_d_tech	*ctrp ;						/* ptr to connector from parent node */
		 public:
						OI_lm_tree_node(OI_d_tech*,OI_lm_tree*) ;
		virtual				~OI_lm_tree_node() ;
		virtual	void			attach(OI_number) = 0 ;				/* attach child contours */
			long			center_distance_squared(long,long) const ;	/* square of distance from center of node to point */
			OI_lm_tree_node		*child() const			{ return((OI_lm_tree_node*)slot()); }
			OI_d_tech		*connector() const		{ return(ctrp); }
			void			connect() ;					/* add connector from parent */
			OI_lm_polygon		*contour() const		{ return((OI_lm_polygon*)&cntr); }
			void			copy_contour(OI_lm_polygon*) ;
//			OI_lm_tree_node		*find_child(OI_d_tech*) const ;			/* locate immediate child corresponding to OI object */
			OI_lm_tree_node		*find_closest_sibling(long,long,OI_number) const ;
			OI_lm_tree_node		*find_closest_parent(long,long,long*,OI_number) const ;
//			OI_lm_tree_node		*find_node(OI_d_tech*) const ;			/* locate descendant corresponding to OI object */
//			OI_lm_tree_node		*find_sibling(OI_d_tech*) const ;		/* locate sibling corresponding to OI object */
		virtual	OI_bool			follows_as_sibling(long,long,OI_number) const = 0 ;	/* chk if node follows arbitrary position if pos is sib */
			OI_number		full_height() const ;
			OI_number		full_width() const ;
		virtual	int			join() = 0 ;					/* join child contours as close as possible */
			OI_lm_tree_node		*last_descendant() const ;			/* find last descendant of node (node itself for leaves) */
			void			layout() ;
		virtual	void			layout_leaf() = 0 ;
			OI_lm_boundary		*lower() const			{ return(cntr.lower()); }
		virtual	int			merge(OI_lm_tree_node*) = 0 ;			/* merge a child's contour into our own */
		virtual	OI_number		obj_offset_x() const ;
		virtual	OI_number		obj_offset_y() const ;
			OI_number		offset_x() const		{ return(off.x); }
			OI_number		offset_y() const		{ return(off.y); }
			OI_lm_tree_node		*parent() const ;
		virtual	void			position_nodes(OI_lm_tree_node*) = 0 ;		/* position node and children */
		virtual	OI_bool			precedes_as_parent(long,long,OI_number) const = 0 ;	/* chk if node precedes arbitrary position if pos is child */
			OI_lm_tree_node		*predecessor() const		{ return((OI_lm_tree_node*)prev()); }
			void			remove_connector() ;
			void			set_child(OI_lm_tree_node *p)	{ set_slot(p); if (p) p->set_prev(NULL); }
			void			set_offset(OI_number x, OI_number y)	{ off.x=x; off.y=y; }
			void			set_parent(OI_lm_tree_node *p)	{ set_head(p); }
			void			set_sibling(OI_lm_tree_node *p)	{ set_next(p); if (p) p->set_prev(this); }
			OI_lm_tree_node		*sibling() const		{ return((OI_lm_tree_node*)next()); }
		virtual	void			size_change() ;
			OI_lm_tree_node		*traverse_sibling() const ;			/* traverse sibling chain */
			void			disconnect(OI_bool) ;
			OI_lm_boundary		*upper() const			{ return(cntr.upper()); }
		} ;

		class	OI_lm_horz_tree_node : public OI_lm_tree_node {
		 public:
						OI_lm_horz_tree_node(OI_d_tech*,OI_lm_tree*) ;
		virtual				~OI_lm_horz_tree_node() ;
		virtual	void			attach(OI_number) ;
		virtual	OI_bool			follows_as_sibling(long,long,OI_number) const ;
		virtual	int			join() ;
		virtual	void			layout_leaf() ;
		virtual	int			merge(OI_lm_tree_node*) ;
			int			offset(int,int,int,int,int,int) const ;
		virtual	void			position_nodes(OI_lm_tree_node*) ;
		virtual	OI_bool			precedes_as_parent(long,long,OI_number) const ;
		} ;

		class	OI_lm_vert_tree_node : public OI_lm_tree_node {
		 public:
						OI_lm_vert_tree_node(OI_d_tech*,OI_lm_tree*) ;
		virtual				~OI_lm_vert_tree_node() ;
		virtual	void			attach(OI_number) ;
		virtual	OI_bool			follows_as_sibling(long,long,OI_number) const ;
		virtual	int			join() ;
		virtual	void			layout_leaf() ;
		virtual	int			merge(OI_lm_tree_node*) ;
			int			offset(int,int,int,int,int,int) const ;
		virtual	void			position_nodes(OI_lm_tree_node*) ;
		virtual	OI_bool			precedes_as_parent(long,long,OI_number) const ;
		} ;

#endif /* OI_Plmtree_H */
