core/vgui/vgui_parent_child_link.h
Go to the documentation of this file.
00001 #ifndef vgui_parent_child_link_h_
00002 #define vgui_parent_child_link_h_
00003 //:
00004 // \file
00005 // \brief  Describes the relationship between a parent and child tableau.
00006 // \author fsm
00007 //
00008 //  Contains class  vgui_parent_child_link
00009 //
00010 // \verbatim
00011 //  Modifications
00012 //   17-Sep-2002 K.Y.McGaul - Added doxygen style comments.
00013 // \endverbatim
00014 
00015 #include <vcl_iosfwd.h>
00016 #include <vcl_vector.h>
00017 
00018 class  vgui_event;
00019 class  vgui_tableau;
00020 struct vgui_tableau_sptr;
00021 struct vgui_parent_child_link_impl;   // implementation class.
00022 
00023 //: Describes the relationship between a parent and child tableau.
00024 //
00025 // Q: what is a vgui_parent_child_link?
00026 // A: These are essentially specialized smart pointers. A parent_child_link
00027 // refers to an edge in the tableau [di]graph. A tableau acquires
00028 // a child by creating a parent_child_link with itself as parent and the child
00029 // as, er, child. The parent_child_links are responsible for storing this
00030 // relation behind the scenes so that it can be queried and used for, say,
00031 // propagating redraw requests.
00032 //
00033 // Semantics:
00034 // Assigning a parent_child_link to a parent_child_link
00035 // \code
00036 //   lhs = rhs;
00037 // \endcode
00038 // doesn't change the graph, only the lhs which no longer refers
00039 // to the edge it used to refer to.
00040 // Calling set_child(t) on a parent_child_link changes the graph (the given
00041 // tableau *t becomes the new child of the parent_child_link).
00042 // E.g.:
00043 // \code
00044 //   vgui_parent_child_link left (this,child);
00045 //   vgui_parent_child_link right(this,child);
00046 //   bool v = (left == right); // this is false
00047 // \endcode
00048 // or :
00049 // \code
00050 //   vgui_parent_child_link e(this,child);
00051 //   vgui_parent_child_link f=e;
00052 //   bool v = (e == f); // this is true
00053 // \endcode
00054 //
00055 // You can use a parent_child_link much like a pointer to tableaux. It
00056 // will behave like the child of the parent_child_link :
00057 // \code
00058 //   left->handle(e);   // same as left.child()->handle(e);
00059 //   right->method();   // same as right.child()->method();
00060 // \endcode
00061 // In particular, you may put your parent_child_links into vectors, trees,
00062 // stacks etc if that is useful for your purposes. Repeat :
00063 // copying a parent_child_link does not create a new edge in the graph, only
00064 // another handle to the same edge.
00065 //
00066 // Attempting to create a non-empty parent_child_link whose parent and child
00067 // are the same tableau causes an abort().
00068 struct vgui_parent_child_link
00069 {
00070  private:
00071   VCL_SAFE_BOOL_DEFINE;
00072  public:
00073   //: Constructor - creates a default vgui_parent_child_link.
00074   vgui_parent_child_link() : pimpl(0) {}
00075 
00076   //: Constructor - creates a vgui_parent_child_link same as the given one.
00077   vgui_parent_child_link(vgui_parent_child_link const &);
00078 
00079   //: Constructor - takes the parent tableau.
00080   //  The 'parent' parameter is the self pointer ('this') of the tableau
00081   //  which intends to hold the parent_child_link. It may \e not be a null
00082   //  pointer.
00083   //  To make an uninitialized parent_child_link, use the default constructor.
00084   vgui_parent_child_link(vgui_tableau * parent /* child is zero */);
00085 
00086   //: Constructor - takes the parent and child tableaux.
00087   //  The 'parent' parameter is the self pointer ('this') of the tableau
00088   //  which intends to hold the parent_child_link. It may \e not be a null
00089   //  pointer.
00090   //  To make an uninitialized parent_child_link, use the default constructor.
00091   vgui_parent_child_link(vgui_tableau * parent, vgui_tableau_sptr const &child);
00092 
00093   //: Destructor - delete this parent_child_link.
00094   ~vgui_parent_child_link();
00095 
00096   //: Make this parent_child_link equal to the given one.
00097   vgui_parent_child_link &operator=(vgui_parent_child_link const &);
00098 
00099   //: Returns true if this parent_child_link is the same as the given link.
00100   //  Links are equal if they have the same implementation. Merely having
00101   //  the same parent and child does not imply equality.
00102   bool operator==(vgui_parent_child_link const &s) const { return pimpl == s.pimpl; }
00103 
00104   //: Comparing a parent_child_link with a tableau compares the child.
00105   bool operator==(vgui_tableau_sptr const &t) const;
00106 
00107   //: Returns the parent tableau for this parent_child_link.
00108   vgui_tableau_sptr parent() const;
00109 
00110   //: Returns the child tableau for this parent_child_link.
00111   vgui_tableau_sptr child () const;
00112 
00113   //: Return true if both parent and child tableaux exist.
00114   operator safe_bool () const;
00115 
00116   //: Return false if both parent and child tableaux exist.
00117   bool operator!() const;
00118 
00119   //: Return a pointer to the child tableau.
00120   //  A parent_child_link behaves more like its child than its parent.
00121   operator vgui_tableau_sptr () const;
00122 
00123   //: Return a pointer to the child tableau.
00124   //  A parent_child_link behaves more like its child than its parent.
00125   vgui_tableau *operator -> () const;
00126 
00127   //: Let the child tableau handle the event.
00128   //  A parent_child_link behaves more like its child than its parent.
00129   bool handle(vgui_event const &e);
00130 
00131   //: Make the given tableau the child tableau in this relationship.
00132   //  A parent_child_link's parent pointer cannot be changed because there is no
00133   //  legitimate use for that.
00134   //  Attempting to set the child to be the same tableau as the parent will
00135   //  cause an abort().
00136   void assign(vgui_tableau_sptr const &); // sets child only
00137 
00138   // ---------- statics ----------
00139 
00140   //: Push all children of 'tab' onto the vector.
00141   static void get_children_of(vgui_tableau_sptr const &tab,
00142                               vcl_vector<vgui_tableau_sptr> *);
00143 
00144   //: Push all parents of 'tab' onto the vector.
00145   static void get_parents_of (vgui_tableau_sptr const &tab,
00146                               vcl_vector<vgui_tableau_sptr> *);
00147 
00148   //: In all parent_child_links, replace old_child with new_child.
00149   static void replace_child_everywhere (vgui_tableau_sptr const &old_child,
00150                                         vgui_tableau_sptr const &new_child);
00151 
00152  private:
00153   friend class vgui_tableau;
00154   // Pointer to implementation
00155   vgui_parent_child_link_impl *pimpl;
00156 };
00157 
00158 vcl_ostream & operator<<(vcl_ostream &, vgui_parent_child_link const &);
00159 
00160 #endif // vgui_parent_child_link_h_