core/vgui/vgui_displaybase_tableau.cxx
Go to the documentation of this file.
00001 // This is core/vgui/vgui_displaybase_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   14 Sep 1999
00009 // \brief  See vgui_displaybase_tableau.h for a description of this file.
00010 
00011 #include "vgui_displaybase_tableau.h"
00012 #include "vgui_macro.h"
00013 
00014 #include <vcl_iostream.h>
00015 #include <vcl_vector.h>
00016 #include <vcl_algorithm.h>
00017 #include <vcl_utility.h> // for vcl_pair<,>
00018 
00019 #include <vgui/vgui_gl.h>
00020 #include <vgui/vgui_glu.h>
00021 #include <vgui/vgui_event.h>
00022 #include <vgui/vgui_message.h>
00023 #include <vgui/vgui_style.h>
00024 #include <vgui/vgui_soview.h>
00025 
00026 bool vgui_displaybase_tableau_selection_callback::select(unsigned)
00027 {
00028   return false;
00029 }
00030 
00031 bool vgui_displaybase_tableau_selection_callback::deselect(unsigned)
00032 {
00033   return false;
00034 }
00035 
00036 bool vgui_displaybase_tableau_selection_callback::deselect_all()
00037 {
00038   return false;
00039 }
00040 
00041 vgui_displaybase_tableau::vgui_displaybase_tableau()
00042 {
00043   id = vgui_soview::create_id();
00044 
00045   gl_mode = GL_RENDER;
00046   highlighted = 0;
00047   gl_display_list = GL_INVALID_VALUE;
00048 
00049   cb_ = 0;
00050 
00051   current_grouping = "default";
00052   groupings.clear();
00053 }
00054 
00055 vgui_displaybase_tableau::~vgui_displaybase_tableau()
00056 {
00057 }
00058 
00059 void vgui_displaybase_tableau::set_selection_callback(vgui_displaybase_tableau_selection_callback* cb)
00060 {
00061   cb_ = cb;
00062 }
00063 
00064 void vgui_displaybase_tableau::add(vgui_soview* object)
00065 {
00066 #ifndef NDEBUG
00067   vcl_vector<vgui_soview*>::iterator i = vcl_find(objects.begin(), objects.end(), object);
00068   if (i == objects.end())
00069   {
00070 #endif
00071     objects.push_back(object);
00072     vcl_map< vcl_string , vgui_displaybase_tableau_grouping >::iterator it = groupings.find( current_grouping );
00073     if ( it == groupings.end() )
00074     {
00075       vgui_displaybase_tableau_grouping temp;
00076       temp.style = NULL;
00077       temp.hide = false;
00078       temp.color_override = false;
00079       temp.line_width_override = false;
00080       temp.point_size_override = false;
00081       temp.objects.push_back( object );
00082       groupings.insert( vcl_pair< vcl_string , vgui_displaybase_tableau_grouping >( current_grouping , temp ) );
00083     }
00084     else
00085       it->second.objects.push_back( object );
00086 #ifndef NDEBUG
00087   }
00088   else
00089     vcl_cerr << "Warning: attempt to add an soview twice.\n";
00090 #endif
00091 }
00092 
00093 void vgui_displaybase_tableau::remove(vgui_soview*& object)
00094 {
00095   if (object->get_id() == highlighted)
00096   {
00097     // if the point to be removed is the currently highlighted
00098     // one, zero out the 'highlighted' field. otherwise the
00099     // point will still be rendered when the pointer moves.
00100     highlighted = 0;
00101   }
00102 
00103   // must first unselect the object, if it's selected
00104   deselect( object->get_id());
00105 
00106   vcl_vector<vgui_soview*>::iterator i = vcl_find(objects.begin(), objects.end(), object);
00107   if (i != objects.end())
00108   {
00109     objects.erase(i);
00110   }
00111 
00112   for ( vcl_map< vcl_string , vgui_displaybase_tableau_grouping >::iterator it = groupings.begin() ;
00113         it != groupings.end(); it++ )  {
00114     vcl_vector<vgui_soview*>::iterator a = vcl_find(it->second.objects.begin(), it->second.objects.end(), object);
00115     if (a != it->second.objects.end()) {
00116       it->second.objects.erase(a);
00117       if ( it->second.objects.size() == 0 )  {
00118         groupings.erase( it );
00119       }
00120       delete object;
00121       break; // found obj, stop iterating
00122     }
00123   }
00124 }
00125 
00126 //: clear all soviews from the display.
00127 //  The soviews must be deleted otherwise we have a big memory leak.
00128 //  It is not clear that the design intended that the creator of the
00129 //  soview is responsible for deleting it.  In any case, such management
00130 //  would be impossible without reference counting.  If users are going
00131 //  to keep soviews for personal use, then the whole soview scheme
00132 //  should be changed to smart pointers. JLM
00133 //
00134 void vgui_displaybase_tableau::clear()
00135 {
00136   highlighted = 0;
00137   deselect_all();
00138 
00139   // destroy the objects
00140   for (vcl_vector<vgui_soview*>::iterator so_iter = objects.begin();
00141        so_iter != objects.end(); ++so_iter)
00142   {
00143     delete *so_iter;
00144   }
00145 
00146   objects.clear();
00147 
00148   for ( vcl_map< vcl_string , vgui_displaybase_tableau_grouping >::iterator it = groupings.begin() ;
00149         it != groupings.end() ;
00150         it++ )
00151   {
00152     it->second.objects.clear();
00153   }
00154 
00155   groupings.clear();
00156 }
00157 
00158 void vgui_displaybase_tableau::draw_soviews_render()
00159 {
00160   vgui_macro_report_errors;
00161   {
00162     for (vcl_map< vcl_string , vgui_displaybase_tableau_grouping >::iterator it = groupings.begin();
00163          it != groupings.end();
00164          it++ )
00165     {
00166       if ( ! it->second.hide )
00167       {
00168         for (vcl_vector<vgui_soview*>::iterator so_iter= it->second.objects.begin();
00169              so_iter != it->second.objects.end(); ++so_iter)
00170         {
00171           vgui_soview *so = *so_iter;
00172           vgui_style_sptr style = so->get_style();
00173 
00174           if ( ! it->second.style && style )
00175             style->apply_all();
00176           else if ( ! style && it->second.style )
00177             it->second.style->apply_all();
00178           else if ( style && it->second.style )
00179           {
00180             if ( it->second.color_override )
00181               it->second.style->apply_color();
00182             else
00183               style->apply_color();
00184 
00185             if ( it->second.line_width_override )
00186               it->second.style->apply_line_width();
00187             else
00188               style->apply_line_width();
00189 
00190             if ( it->second.point_size_override )
00191               it->second.style->apply_point_size();
00192             else
00193               style->apply_point_size();
00194           }
00195 
00196           if (is_selected(so->get_id()))
00197             glColor3f(1.0f, 0.0f, 0.0f);
00198 
00199           so->draw();
00200         }//  for all soviews
00201       }
00202     }
00203   }
00204   vgui_macro_report_errors;
00205 }
00206 
00207 
00208 void vgui_displaybase_tableau::draw_soviews_select()
00209 {
00210   // push the name of this displaylist onto the name stack
00211   glPushName(id);
00212 
00213   glPushName(0); // will be replaced by the id of each object
00214 
00215   for ( vcl_map< vcl_string , vgui_displaybase_tableau_grouping >::iterator it = groupings.begin();
00216         it != groupings.end();
00217         it++ )
00218   {
00219     if ( ! it->second.hide )
00220     {
00221       for (vcl_vector<vgui_soview*>::iterator so_iter=it->second.objects.begin();
00222            so_iter != it->second.objects.end(); ++so_iter)
00223       {
00224         // only highlight if the so is selectable
00225         vgui_soview* so = *so_iter;
00226         if ( so->get_selectable())
00227         {
00228           so->load_name();
00229           so->draw_select();
00230         }
00231       }//  for all soviews
00232     }
00233   }
00234 
00235   // remove name of last object
00236   glPopName();
00237 
00238   // remove the name of the displaylist from the name stack
00239   glPopName();
00240 }
00241 
00242 
00243 bool vgui_displaybase_tableau::handle(const vgui_event& e)
00244 {
00245   if (e.type == vgui_DRAW)
00246   {
00247     if (gl_mode == GL_SELECT)
00248       draw_soviews_select();
00249     else
00250       draw_soviews_render();
00251 
00252     return true;
00253   }
00254   else
00255     return vgui_tableau::handle(e);
00256 }
00257 
00258 bool vgui_displaybase_tableau::is_selected(unsigned iden)
00259 {
00260   vcl_vector<unsigned>::iterator result = vcl_find(selections.begin(), selections.end(), iden);
00261   return result != selections.end();
00262 }
00263 
00264 vcl_vector<vgui_soview*> vgui_displaybase_tableau::get_selected_soviews() const
00265 {
00266   vcl_vector<vgui_soview*> svs;
00267   for (unsigned i=0; i<selections.size(); ++i)
00268   {
00269     svs.push_back(vgui_soview::id_to_object(selections[i]));
00270   }
00271   return svs;
00272 }
00273 
00274 vcl_vector<unsigned> vgui_displaybase_tableau::get_all_ids() const
00275 {
00276   vcl_vector<unsigned> ids;
00277   for (unsigned int i=0; i< objects.size(); ++i)
00278     ids.push_back(objects[i]->get_id());
00279 
00280   return ids;
00281 }
00282 
00283 bool vgui_displaybase_tableau::select(unsigned iden)
00284 {
00285   vcl_vector<unsigned>::iterator result = vcl_find(selections.begin(), selections.end(), iden);
00286   if (result == selections.end())
00287   {
00288     // add selection to vcl_list
00289     selections.push_back(iden);
00290 
00291     // notify so's observers
00292     vgui_soview* so = vgui_soview::id_to_object(iden);
00293 
00294     if ( so->get_selectable())
00295     {
00296       vgui_message msg;
00297 #if 0
00298       msg.text = "soview select";
00299 #endif // 0
00300       msg.user = (void const*) &vgui_soview::msg_select;
00301       so->notify(msg);
00302 
00303       if (cb_) cb_->select(iden);
00304     }
00305   }
00306 
00307   return true;
00308 }
00309 
00310 bool vgui_displaybase_tableau::deselect(unsigned iden)
00311 {
00312   vcl_vector<unsigned>::iterator result = vcl_find(selections.begin(), selections.end(), iden);
00313   if (result != selections.end())
00314   {
00315     // remove selection from vcl_list
00316     selections.erase(result);
00317 
00318     // notify so's observers
00319     vgui_soview* so = vgui_soview::id_to_object(iden);
00320     vgui_message msg;
00321 #if 0
00322     msg.text = "soview deselect";
00323 #endif // 0
00324     msg.user = (void const*) &vgui_soview::msg_deselect;
00325     so->notify(msg);
00326 
00327     if (cb_) cb_->deselect(iden);
00328   }
00329 
00330   return true;
00331 }
00332 
00333 bool vgui_displaybase_tableau::deselect_all()
00334 {
00335   // this is a bit inelegant but you have to make a copy
00336   // of the selections vcl_list as sending the deselect message
00337   // may actually change the selections
00338 
00339   vcl_vector<unsigned> oldselections = selections;
00340 
00341   for (vcl_vector<unsigned>::iterator s_iter = oldselections.begin();
00342        s_iter != oldselections.end(); ++s_iter )
00343   {
00344     unsigned iden = *s_iter;
00345 
00346     // notify so's observers
00347     vgui_soview* so = vgui_soview::id_to_object(iden);
00348     vgui_message msg;
00349     msg.user = (void const*)&vgui_soview::msg_deselect;
00350     so->notify(msg);
00351 
00352     if (cb_) cb_->deselect(iden);
00353   }
00354 
00355   selections.clear();
00356   this->post_redraw();
00357 
00358   return true;
00359 }
00360 
00361 
00362 vgui_soview* vgui_displaybase_tableau::get_highlighted_soview()
00363 {
00364     return vgui_soview::id_to_object(highlighted);
00365 }
00366 
00367 vgui_soview* vgui_displaybase_tableau::contains_hit(vcl_vector<unsigned> names)
00368 {
00369   for (vcl_vector<vgui_soview*>::iterator i = objects.begin() ;
00370        i != objects.end() ; ++i)
00371   {
00372     // get id of soview
00373     unsigned soview_id = (*i)->get_id();
00374 #ifdef DEBUG
00375     vcl_cerr << "vgui_displaybase_tableau::contains_hit soview_id=" << soview_id << '\n';
00376 #endif
00377     vcl_vector<unsigned>::iterator ni = vcl_find(names.begin(), names.end(), soview_id);
00378     if (ni != names.end())
00379       return *i;
00380   }
00381 
00382   return 0;
00383 }
00384 
00385 vgui_displaybase_tableau_grouping* vgui_displaybase_tableau::get_grouping_ptr( vcl_string t_name )
00386 {
00387   vcl_map< vcl_string , vgui_displaybase_tableau_grouping >::iterator it = groupings.find( t_name );
00388   if ( it != groupings.end() )
00389     return & it->second;
00390   else
00391     return NULL;
00392 }
00393 
00394 vcl_vector< vcl_string > vgui_displaybase_tableau::get_grouping_names()
00395 {
00396   vcl_vector< vcl_string > to_return;
00397 
00398   for ( vcl_map< vcl_string , vgui_displaybase_tableau_grouping >::iterator it = groupings.begin();
00399         it != groupings.end();
00400         it++ )
00401   {
00402     to_return.push_back( it->first );
00403   }
00404 
00405   return to_return;
00406 }
00407