core/vgui/vgui_displaylist2D_tableau.cxx
Go to the documentation of this file.
00001 // This is core/vgui/vgui_displaylist2D_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_displaylist2D_tableau.h for a description of this file.
00010 
00011 #include "vgui_displaylist2D_tableau.h"
00012 
00013 #include <vcl_iostream.h>
00014 #include <vcl_vector.h>
00015 #include <vcl_cassert.h>
00016 
00017 #include <vgui/vgui_gl.h>
00018 #include <vgui/vgui_glu.h>
00019 
00020 #include <vgui/vgui.h>
00021 #include <vgui/vgui_utils.h>
00022 #include <vgui/vgui_event.h>
00023 #include <vgui/vgui_projection_inspector.h>
00024 #include <vgui/vgui_soview2D.h>
00025 #include <vgui/vgui_style.h>
00026 
00027 bool vgui_displaylist2D_tableau::handle(const vgui_event& e)
00028 {
00029   // if mouse leaves the context then unhighlight
00030   // the highlit object
00031   if (e.type == vgui_LEAVE) {
00032     this->highlight(0);
00033     post_overlay_redraw();
00034   }
00035 
00036   if (e.type == vgui_OVERLAY_DRAW)
00037   {
00038     unsigned hghlghted = this->get_highlighted();
00039     if (hghlghted)
00040     {
00041       vgui_soview* so = vgui_soview::id_to_object(hghlghted);
00042       vgui_style_sptr style = so->get_style();
00043       if ( style ) {
00044         style->apply_point_size();
00045         style->apply_line_width();
00046       }
00047       glColor3f(0.0,0.0,1.0);
00048       so->draw();
00049     }
00050   }
00051 
00052   return vgui_displaybase_tableau::handle(e);
00053 }
00054 
00055 //: Return indices of my elements which are near (x,y)
00056 void vgui_displaylist2D_tableau::get_hits(float x, float y,
00057                                           vcl_vector<unsigned>& my_hits)
00058 {
00059   // select objects within 20 pixels of the mouse
00060   GLuint *ptr = vgui_utils::enter_pick_mode(x,y,20);
00061 
00062   this->gl_mode = GL_SELECT;
00063   this->handle(vgui_event(vgui_DRAW));
00064   this->gl_mode = GL_RENDER;
00065 
00066   int num_hits = vgui_utils::leave_pick_mode();
00067 
00068   // get all hits
00069   vcl_vector<vcl_vector<unsigned> > hits;
00070   vgui_utils::process_hits(num_hits, ptr, hits);
00071 
00072   // for each hit get the name of the soview if it is
00073   // being managed by this vcl_list
00074   //
00075   // Each hit from a display list has two entries. The first is the id
00076   // of the display list, and the second is the id of the soview. See
00077   // vgui_displaybase_tableau::draw_soviews_select(). Thus, an object
00078   // belongs to this display list iff the first hit number is this
00079   // list's id.
00080 
00081   for (vcl_vector<vcl_vector<unsigned> >::iterator i=hits.begin();
00082        i != hits.end(); ++i)
00083   {
00084     vcl_vector<unsigned> const& names = *i;
00085 
00086     if ( ! names.empty() && names[0] == this->get_id() )
00087     {
00088       // this assertion is based on the code in
00089       // vgui_displaybase_tableau::draw_soviews_select(). If this is
00090       // not true, then please review the assumptions about the
00091       // selection process before updating the assertion.
00092       //
00093       assert( names.size() == 2 );
00094       my_hits.push_back( names[1] );
00095     }
00096   }
00097 }
00098 
00099 unsigned vgui_displaylist2D_tableau::find_closest(float x, float y,
00100                                                   vcl_vector<unsigned> const& hits)
00101 {
00102   unsigned closest = 0;
00103   float closest_dist = -1; // vnl_numeric_traits<float>::maxval;
00104 
00105   for (vcl_vector<unsigned>::const_iterator h_iter = hits.begin();
00106        h_iter != hits.end(); ++h_iter)
00107   {
00108     // In principle, VXL shouldn't use dynamic_cast since it depends
00109     // on RTTI, and so far (July 2003), we are not allowed to depend
00110     // on RTTI in vxl/core code. However, dynamic_cast is *much*
00111     // safer than static_cast, so I'll sneak this in. Change it to
00112     // static_cast if your compiler breaks.
00113     //
00114     vgui_soview2D* so = dynamic_cast<vgui_soview2D*>(vgui_soview::id_to_object(*h_iter));
00115     assert( so ); // NULL => something is wrong.
00116 
00117     float dist = so->distance_squared(x,y);
00118 #ifdef DEBUG
00119     vcl_cerr << "vgui_displaylist2D_tableau::find_closest distance to " << (void*)so << " is " << dist << '\n';
00120 #endif
00121     if (closest_dist<0 || dist<closest_dist) {
00122       closest_dist = dist;
00123       closest = *h_iter;
00124     }
00125   }// end for
00126 
00127   return closest;
00128 }
00129 
00130 bool vgui_displaylist2D_tableau::motion(int x, int y)
00131 {
00132   vgui_projection_inspector pi;
00133   float ix, iy;
00134   pi.window_to_image_coordinates(x,y, ix,iy);
00135 
00136   vcl_vector<unsigned> hits;
00137   get_hits(x,y,hits);
00138   unsigned closest_id = find_closest(ix,iy,hits);
00139 
00140   if ( closest_id != this->get_highlighted() ) {
00141     this->highlight( closest_id );
00142     post_overlay_redraw();
00143   }
00144 
00145   return false;
00146 }
00147 
00148 bool vgui_displaylist2D_tableau::mouse_down(int x, int y, vgui_button button, vgui_modifier modifier)
00149 {
00150   float ix, iy;
00151   vgui_projection_inspector().window_to_image_coordinates(x,y, ix,iy);
00152 
00153   // selecting
00154   if (button == vgui_LEFT && modifier == 0)
00155   {
00156 #ifdef DEBUG
00157     vcl_cerr << "vgui_displaylist2D_tableau::mouse_down: selecting at " << x << ',' << y << '\n';
00158 #endif
00159     vcl_vector<unsigned> hits;
00160     get_hits(x,y,hits);
00161     unsigned closest_id = find_closest(ix,iy,hits);
00162     if (closest_id) {
00163       this->select(closest_id);
00164       this->post_redraw();
00165       return true;
00166     }
00167 
00168     return false;
00169   }// end selecting
00170 
00171   // deselecting
00172   else if (button == vgui_MIDDLE)
00173   {
00174     if (modifier & vgui_SHIFT)
00175     {
00176 #ifdef DEBUG
00177       vcl_cerr << "vgui_displaylist2D_tableau::mouse_down: deselecting all\n";
00178 #endif
00179       this->deselect_all();
00180       this->post_redraw();
00181       return false;
00182     }
00183 
00184 #ifdef DEBUG
00185     vcl_cerr << "vgui_displaylist2D_tableau::mouse_down: deselecting at " << x << ' ' << y << '\n';
00186 #endif
00187     vcl_vector<unsigned> hits;
00188     get_hits(x,y,hits);
00189     unsigned closest_id = find_closest(ix,iy,hits);
00190     if (closest_id) {
00191       this->deselect(closest_id);
00192       this->post_redraw();
00193       return true;
00194     }
00195     return false;
00196   }// end deselecting
00197   return false;
00198 }