core/vgui/vgui_deck_tableau.cxx
Go to the documentation of this file.
00001 // This is core/vgui/vgui_deck_tableau.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Philip C. Pritchett, RRG, University of Oxford
00008 // \date   13 Sep 1999
00009 // \brief  See vgui_deck_tableau.h for a description of this file.
00010 
00011 #include "vgui_deck_tableau.h"
00012 
00013 #include <vcl_iostream.h>
00014 #include <vcl_vector.h>
00015 
00016 #include <vgui/vgui_event.h>
00017 #include <vgui/vgui_menu.h>
00018 #include <vgui/vgui_command.h>
00019 #include <vgui/vgui_popup_params.h>
00020 
00021 static bool debug=false;
00022 
00023 //----------------------------------------------------------------------------
00024 //: Constructor - don't use this, use vgui_deck_tableau_new.
00025 //  Make a deck with two children, listed top to bottom.
00026 vgui_deck_tableau::vgui_deck_tableau(vgui_tableau_sptr const& child0,
00027                                      vgui_tableau_sptr const& child1) : index_(-1)
00028 {
00029   add(child0);
00030   add(child1);
00031 }
00032 
00033 //----------------------------------------------------------------------------
00034 //: Constructor - don't use this, use vgui_deck_tableau_new.
00035 //  Make a deck with three children, listed top to bottom.
00036 vgui_deck_tableau::vgui_deck_tableau(vgui_tableau_sptr const& child0,
00037                                      vgui_tableau_sptr const& child1,
00038                                      vgui_tableau_sptr const& child2) : index_(-1)
00039 {
00040   add(child0);
00041   add(child1);
00042   add(child2);
00043 }
00044 
00045 //----------------------------------------------------------------------------
00046 //: Destructor - called by vgui_deck_tableau_sptr.
00047 vgui_deck_tableau::~vgui_deck_tableau() {}
00048 
00049 //----------------------------------------------------------------------------
00050 //: Handle events by passing to the current child tableau.
00051 bool vgui_deck_tableau::handle(const vgui_event& event)
00052 {
00053   // First pass events to the default handle method (this calls key_press, etc).
00054   if (vgui_tableau::handle(event))
00055     return true;
00056 
00057   if (!index_ok(index_))
00058     return false;
00059 
00060   // Then pass events to the current child tableau.
00061   vgui_tableau_sptr t = children[index_];
00062   return t->handle(event);
00063 }
00064 
00065 //----------------------------------------------------------------------------
00066 //: Send info to cerr - called when user presses '?' in the rendering area.
00067 //  Over-rides function in vgui_tableau.
00068 //  This function is called by the default handle() function in vgui_tableau.
00069 bool vgui_deck_tableau::help()
00070 {
00071   vcl_cerr << "\n-- vgui_deck_tableau ----------------------------\n"
00072            << "|     keys                                      |\n"
00073            << "| `PageUp' and `PageDown'  switch current child |\n"
00074            << "-------------------------------------------------\n\n";
00075 
00076   return false;
00077 }
00078 
00079 //----------------------------------------------------------------------------
00080 //: Uses PageUp and PageDown events - called when user presses a key.
00081 //  Over-rides function in vgui_tableau.
00082 //  This function is called by the default handle() function in vgui_tableau.
00083 bool vgui_deck_tableau::key_press(int x, int y, vgui_key key, vgui_modifier)
00084 {
00085   if (debug)
00086     vcl_cerr << "vgui_deck_tableau::key_press " << key << vcl_endl;
00087 
00088   switch (key)
00089   {
00090    case vgui_PAGE_UP:
00091     this->next();
00092     if (index_ok(index_) && children[index_]) {
00093       vgui_event e(vgui_ENTER);
00094       e.wx = x;
00095       e.wy = y;
00096       children[index_]->handle(e);
00097     }
00098     this->post_redraw();
00099     return true;
00100    case vgui_PAGE_DOWN:
00101     this->prev();
00102     if (index_ok(index_) && children[index_]) {
00103       vgui_event e(vgui_ENTER);
00104       e.wx = x;
00105       e.wy = y;
00106       children[index_]->handle(e);
00107     }
00108     this->post_redraw();
00109     return true;
00110    default:
00111     return false;
00112   }
00113 }
00114 
00115 //----------------------------------------------------------------------------
00116 //: Add a tableau to the deck.
00117 //  It is placed on top and made current.
00118 //  Override virtual base class method.
00119 bool vgui_deck_tableau::add_child(vgui_tableau_sptr const& t)
00120 {
00121   children.push_back( vgui_parent_child_link(this,t) );
00122   index_ = size()-1;
00123   observers.notify();
00124   post_redraw();
00125   return true;
00126 }
00127 
00128 //----------------------------------------------------------------------------
00129 //: Remove the given child tableau from the deck.
00130 void vgui_deck_tableau::remove(vgui_tableau_sptr const& t)
00131 {
00132   if (!remove_child(t))
00133     vcl_cerr << __FILE__ " no such child tableau : " << t << vcl_endl;
00134 }
00135 
00136 //----------------------------------------------------------------------------
00137 //: Remove the given child tableau from the deck.
00138 //  Override virtual base class  method
00139 bool vgui_deck_tableau::remove_child(vgui_tableau_sptr const& t)
00140 {
00141   for (vcl_vector<vgui_parent_child_link>::iterator i = children.begin() ; i!=children.end() ; ++i)
00142     if ( (*i) == t ) {
00143       children.erase(i);
00144       // Index must be allowed to go to -1 if all are deleted, so don't
00145       // check for zero
00146       --index_;
00147       observers.notify();
00148       return true;
00149     }
00150   return false;
00151 }
00152 
00153 
00154 //----------------------------------------------------------------------------
00155 //: Returns the index of the currently active child tableau.
00156 vgui_tableau_sptr vgui_deck_tableau::current()
00157 {
00158   if (index_ok(index_))
00159     return children[index_];
00160 
00161   return 0;
00162 }
00163 
00164 //----------------------------------------------------------------------------
00165 //: Returns the tableau at the given index in the list of child tableau.
00166 vgui_tableau_sptr vgui_deck_tableau::get_tableau_at(int tab_pos)
00167 {
00168   if (index_ok(tab_pos))
00169     return children[tab_pos];
00170   return 0;
00171 }
00172 
00173 //----------------------------------------------------------------------------
00174 //: Returns the number of child tableaux.
00175 int vgui_deck_tableau::size()
00176 {
00177   return children.size();
00178 }
00179 
00180 //----------------------------------------------------------------------------
00181 //: Make the child tableau with the given position the active child.
00182 void vgui_deck_tableau::index(int v)
00183 {
00184   if (index_ok(v)) index_ = v;
00185   if (debug)
00186     vcl_cerr << "vgui_deck_tableau::index " << index_ << vcl_endl;
00187   observers.notify();
00188 }
00189 
00190 //----------------------------------------------------------------------------
00191 //: Make the top tableau current.
00192 void vgui_deck_tableau::begin()
00193 {
00194   if (index_ok(0))
00195     index_ = 0;
00196 
00197   if (debug)
00198     vcl_cerr << "vgui_deck_tableau::begin " << index_ << vcl_endl;
00199   observers.notify();
00200 }
00201 
00202 //----------------------------------------------------------------------------
00203 //: Make the next tableau down the list current.
00204 void vgui_deck_tableau::next()
00205 {
00206   unsigned int tmp = index_;
00207 
00208   if (tmp+1 >= children.size())
00209     tmp=0;
00210   else
00211     ++tmp;
00212 
00213   if (index_ok(tmp))
00214     index_=tmp;
00215 
00216   if (debug)
00217     vcl_cerr << "vgui_deck_tableau::next " << index_ << vcl_endl;
00218   observers.notify();
00219 }
00220 
00221 //----------------------------------------------------------------------------
00222 //: Make the next higher tableau current.
00223 void vgui_deck_tableau::prev()
00224 {
00225   int tmp = index_;
00226 
00227   if (tmp == 0)
00228     tmp=children.size()-1;
00229   else
00230     --tmp;
00231 
00232   if (index_ok(tmp))
00233     index_=tmp;
00234 
00235   if (debug)
00236     vcl_cerr << "vgui_deck_tableau::prev " << index_ << vcl_endl;
00237   observers.notify();
00238 }
00239 
00240 //----------------------------------------------------------------------------
00241 //: Returns true if the given integer could be an index to the list of children.
00242 bool vgui_deck_tableau::index_ok(int v) const
00243 {
00244   return v >= 0 && v < int(children.size());
00245 }
00246 
00247 //----------------------------------------------------------------------------
00248 //: Returns the type of this tableau ('vgui_deck_tableau').
00249 vcl_string vgui_deck_tableau::type_name() const { return "vgui_deck_tableau"; }
00250 
00251 //----------------------------------------------------------------------------
00252 //: Returns the filename of the currently active child tableau.
00253 vcl_string vgui_deck_tableau::file_name() const
00254 {
00255   if (index_ok(index_)) {
00256     return children[index_]->file_name();
00257   }
00258   return type_name();
00259 }
00260 
00261 //----------------------------------------------------------------------------
00262 //: Returns a nice version of the name, with info on the currently active child.
00263 vcl_string vgui_deck_tableau::pretty_name() const
00264 {
00265   vcl_string nice_name;
00266   if (index_ok(index_)) {
00267     nice_name += "[current = ";
00268     nice_name += children[index_]->pretty_name();
00269     nice_name += "]";
00270   }
00271   return nice_name;
00272 }
00273 
00274 //----------------------------------------------------------------------------
00275 class vgui_deck_switch_command : public vgui_command
00276 {
00277  public:
00278   vgui_deck_switch_command(vgui_deck_tableau* d, int i) : deck(d), index(i) {}
00279   void execute() { deck->index(index); deck->post_redraw(); }
00280 
00281   vgui_deck_tableau *deck;
00282   int index;
00283 };
00284 
00285 
00286 //----------------------------------------------------------------------------
00287 //: Builds a popup menu for the user to select the active child.
00288 void vgui_deck_tableau::get_popup(const vgui_popup_params& params,
00289                                   vgui_menu &menu)
00290 {
00291   vgui_menu submenu;
00292 
00293   // build child selection menu
00294   vgui_menu selections;
00295 
00296   int count = 0;
00297   vcl_vector<vgui_parent_child_link>::iterator i = children.begin();
00298   for ( ; i!=children.end() ; ++i, ++count) {
00299     selections.add((*i)->file_name().c_str(),
00300                    new vgui_deck_switch_command(this,count));
00301   }
00302 
00303   submenu.add("Select active child", selections);
00304 
00305   if (params.nested)
00306   {
00307     // nested menu style
00308 
00309     vgui_tableau_sptr c = current();
00310 
00311     if (c && params.defaults) submenu.separator();
00312     c->get_popup(params, submenu);
00313     menu.add(type_name(), submenu);
00314   }
00315   else
00316   {
00317     menu.add(type_name(),submenu);
00318 
00319     if (params.recurse) {
00320       vgui_tableau_sptr c = current();
00321       if (c)
00322         c->get_popup(params, menu);
00323     }
00324   }
00325 }