core/vgui/vgui_satellite_tableau.h
Go to the documentation of this file.
00001 // This is core/vgui/vgui_satellite_tableau.h
00002 #ifndef vgui_satellite_tableau_h_
00003 #define vgui_satellite_tableau_h_
00004 //:
00005 // \file
00006 // \author fsm
00007 // \brief  Tableau to turn a non-tableau into a multi-tableau.
00008 //
00009 //  Contains classes: vgui_satellite_tableau_t  vgui_satellite_tableau
00010 //                    vgui_satellite_tableau_t_new vgui_satellite_tableau_new
00011 //
00012 // \verbatim
00013 //  Modifications
00014 //   02-OCT-2002 A.W.Fitzgibbon - Changed overview documentation.
00015 // \endverbatim
00016 
00017 #include <vgui/vgui_menu.h>
00018 #include <vgui/vgui_tableau.h>
00019 #include <vgui/vgui_tableau_sptr.h>
00020 
00021 //----------------------------------------------------------------------------
00022 //: Tableau to turn a non-tableau into a multi-tableau (with client data).
00023 //
00024 // PURPOSE: To turn a non-tableau into a multi-tableau, or
00025 //          to put one tableau into two parts of the tree
00026 //          simultaneously.
00027 //
00028 // EXAMPLE:
00029 //          We are displaying two images, each in its own zoomer
00030 //          and we'd like to have a tableau which takes mouse events
00031 //          from one image and draws a line on the other.  This
00032 //          introduces a "crossover" in the tree which is difficult
00033 //          to handle without vgui_satellite_tableau.
00034 //
00035 // The basic layout we want is like this:
00036 // \verbatim
00037 //                          Adaptor
00038 //                             |
00039 //                             |
00040 //                            grid
00041 //                            / \                         .
00042 //                           /   \                        .
00043 //                          /     \                       .
00044 //                        zoom    zoom
00045 //                         |       |
00046 //                          \     /
00047 //              draw_on_both_children_tableau ("dob")
00048 //                          /     \                       .
00049 //                         |       |
00050 //                       image   image
00051 // \endverbatim
00052 //
00053 // But a single tableau cannot have multiple paths through
00054 // "handle", so we might split "dob" into two helper tableaux,
00055 // which each hold a pointer to the data required to implement
00056 // the drawing.  Then the "handle" methods of each of the helpers
00057 // are just small stubs which call the handle method on "dob",
00058 // telling it whether it's in the "left" tree or the "right" tree.
00059 // \verbatim
00060 //                          Adaptor
00061 //                             |
00062 //                             |
00063 //                      ---- grid ----
00064 //                     /              \                   .
00065 //                  zoom              zoom
00066 //                    |                |
00067 //                    |                |
00068 //                  dob1 - -> dob <- - dob2
00069 //                           /   \                        .
00070 //                          /     \                       .
00071 //            "handle(e,1)"+       +"handle(e,2)"
00072 //                         |       |
00073 //                         |       |
00074 //                       image   image
00075 // \endverbatim
00076 //
00077 // However, this is a small bit of hassle for the writer of "dob", which
00078 // vgui_satellite_tableau makes easier.  Add an extra argument to
00079 // dob::handle(event), which indicates which side the event is on, and then
00080 // put a
00081 //   vgui_satellite_tableau_t<type_of_dob, int>(dob, 1)
00082 // in the left tree and a
00083 //   vgui_satellite_tableau_t<type_of_dob, int>(dob, 2)
00084 // in the right tree.  Then whenever an event goes down the tree
00085 // the satellites call dob::handle with a 1 or a 2, so dob knows
00086 // which way to pass it on...
00087 template <class object, class data>
00088 struct vgui_satellite_tableau_t : public vgui_tableau
00089 {
00090   typedef bool (object::*method)(vgui_event const &, data );
00091 
00092   //: The 'object' type must have a method type_name().
00093   //  It is used to implement the type_name() methods on the satellites.
00094   object *p;
00095 
00096   method  m;
00097 
00098   //: Client data.
00099   //  The 'data' parameter may seem superfluous because one could
00100   //  achieve the same result by having two methods which were used
00101   //  to initialize the satellites. However, if the number of satellites
00102   //  is unknown at compile time, or if there are many of them and it
00103   //  is easier to generate them in code, then the 'data' parameter is
00104   //  necessary.
00105   data    d;
00106 
00107   //: Name.
00108   vcl_string n;
00109 
00110   //: Constructor - don't use this, use vgui_satellite_tableau_t_new.
00111   //  There is no vgui_satellite_tableau_t_sptr for this tableau.
00112   vgui_satellite_tableau_t(object *p_, method m_, data const &d_,
00113                            vcl_string const &n_ = "")
00114     : p(p_), m(m_), d(d_), n(n_) { }
00115 
00116   bool handle(vgui_event const &e) { return (p && m) && (p->*m)(e, d); }
00117 
00118   vcl_string type_name() const
00119   { return vcl_string("vgui_satellite_tableau_t[") + n + vcl_string("]"); }
00120 
00121   vgui_menu a_menu;
00122   void add_popup(vgui_menu &mnu) { mnu.include(a_menu); }
00123 
00124  protected:
00125   ~vgui_satellite_tableau_t() { p = 0; m = 0; }
00126 };
00127 
00128 //----------------------------------------------------------------------------
00129 //: Tableau to turn a non-tableau into a multi-tableau (without client data).
00130 //
00131 //  See vgui_satellite_tableau_t to see what a satellite does.
00132 template <class object>
00133 struct vgui_satellite_tableau : public vgui_tableau
00134 {
00135   typedef bool (object::*method)(vgui_event const &);
00136 
00137   //:The 'object' type must have a method type_name().
00138   // It is used to implement the type_name() methods on the satellites.
00139   object *p;
00140 
00141   method  m;
00142 
00143   //: Name.
00144   vcl_string n;
00145 
00146   //: Constructor - don't use this, use vgui_satellite_tableau_new.
00147   //  There is no vgui_satellite_tableau_sptr for this tableau.
00148   vgui_satellite_tableau(object *p_, method m_, vcl_string const &n_ = "")
00149     : p(p_), m(m_), n(n_) { }
00150 
00151   bool handle(vgui_event const &e) { return (p && m) && (p->*m)(e); }
00152 
00153   vcl_string type_name() const
00154   { return vcl_string("vgui_satellite_tableau[") + n + vcl_string("]"); }
00155 
00156  protected:
00157   ~vgui_satellite_tableau() { p = 0; m = 0; }
00158 };
00159 
00160 //----------------------------------------------------------------------------
00161 #ifdef VCL_SUNPRO_CC_50
00162 # define quirk(x) , x
00163 #else
00164 # define quirk(x) /* */
00165 #endif
00166 
00167 template <class object, class data>
00168 struct vgui_satellite_tableau_t_new : public vgui_tableau_sptr_t<vgui_satellite_tableau_t<object, data> quirk(vgui_tableau_sptr)>
00169 {
00170   // no vgui_make_sptr: this file must be maintained manually.
00171   typedef vgui_satellite_tableau_t<object, data> impl;
00172   typedef vgui_tableau_sptr_t<impl quirk(vgui_tableau_sptr)> base;
00173   typedef typename impl::method method;
00174   vgui_satellite_tableau_t_new(object *p, method m, data const &d,
00175                                vcl_string const&n=""):base(new impl(p,m,d,n)) {}
00176 };
00177 
00178 //----------------------------------------------------------------------------
00179 template <class object>
00180 struct vgui_satellite_tableau_new : public vgui_tableau_sptr_t<vgui_satellite_tableau<object> quirk(vgui_tableau_sptr)>
00181 {
00182   // no vgui_make_sptr: this file must be maintained manually.
00183   typedef vgui_satellite_tableau<object> impl;
00184   typedef vgui_tableau_sptr_t<impl quirk(vgui_tableau_sptr)> base;
00185   typedef typename impl::method method;
00186   vgui_satellite_tableau_new(object *p, method m, vcl_string const &n = "")
00187     : base(new impl(p, m, n)) { }
00188 };
00189 #undef quirk
00190 
00191 //----------------------------------------------------------------------------
00192 // these could be in the .txx file but there would be no point to that.
00193 #undef VGUI_SATELLITE_T_INSTANTIATE
00194 #define VGUI_SATELLITE_T_INSTANTIATE(C, A) \
00195 template struct vgui_satellite_tableau_t<C, A >; \
00196 template struct vgui_satellite_tableau_t_new<C, A >
00197 
00198 #undef VGUI_SATELLITE_INSTANTIATE
00199 #define VGUI_SATELLITE_INSTANTIATE(C) \
00200 template struct vgui_satellite_tableau<C >; \
00201 template struct vgui_satellite_tableau_new<C >
00202 
00203 #endif // vgui_satellite_tableau_h_