core/vgui/vgui_tview_tableau.cxx
Go to the documentation of this file.
00001 // This is core/vgui/vgui_tview_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   12 Oct 1999
00009 // \brief  See vgui_tview_tableau.h for a description of this file.
00010 
00011 #include "vgui_tview_tableau.h"
00012 
00013 #include <vcl_string.h>
00014 #include <vcl_cmath.h>
00015 #include <vcl_iostream.h>
00016 
00017 #include <vgui/vgui_gl.h>
00018 #include <vgui/vgui_event.h>
00019 #include <vgui/vgui_tableau.h>
00020 #include <vgui/vgui_deck_tableau.h>
00021 #include <vgui/vgui_composite_tableau.h>
00022 #include <vgui/vgui_projection_inspector.h>
00023 #include <vgui/vgui_listmanager2D_tableau.h>
00024 #include <vgui/vgui_popup_params.h>
00025 #include <vgui/vgui_menu.h>
00026 
00027 vcl_string vgui_tview_tableau::type_name() const {return "vgui_tview_tableau";}
00028 
00029 
00030 vgui_tview_tableau::vgui_tview_tableau(vgui_tableau_sptr const& t)
00031   : vgui_wrapper_tableau(t)
00032   , spacing(10)
00033   , icon_height(2)
00034   , icon_width(2)
00035   , active_icon(0)
00036   , closest_icon(0)
00037 {
00038 }
00039 
00040 
00041 vgui_tview_tableau::~vgui_tview_tableau()
00042 {
00043 }
00044 
00045 
00046 static void draw_rect(float x, float y, float  w, float h)
00047 {
00048   glBegin(GL_POLYGON);
00049   glVertex2f(x-w,y-h);
00050   glVertex2f(x+w,y-h);
00051   glVertex2f(x+w,y+h);
00052   glVertex2f(x-w,y+h);
00053   glEnd();
00054 }
00055 
00056 static void draw_border(float x, float y, float  w, float h, int lt)
00057 {
00058   glLineWidth(lt);
00059 
00060   glBegin(GL_LINE_LOOP);
00061   glVertex2f(x-w,y-h);
00062   glVertex2f(x+w,y-h);
00063   glVertex2f(x+w,y+h);
00064   glVertex2f(x-w,y+h);
00065   glEnd();
00066 }
00067 
00068 
00069 void vgui_tview_tableau::draw_tableau_icon(float x, float y)
00070 {
00071   draw_rect(x,y,icon_width,icon_height);
00072 
00073   glColor3f(1,1,1);
00074   glDisable(GL_LINE_STIPPLE);
00075   //glLineWidth(2);
00076 
00077   draw_border(x,y,icon_width, icon_height, 2);
00078 }
00079 
00080 
00081 void vgui_tview_tableau::draw_tview_icon(float x, float y)
00082 {
00083   glColor3f(1,0,0);
00084   draw_rect(x-icon_width/2.0f, y-icon_height/2.0f, icon_width/2.0f, icon_height/2.0f);
00085 
00086   glColor3f(0,1,0);
00087   draw_rect(x-icon_width/2.0f, y+icon_height/2.0f, icon_width/2.0f, icon_height/2.0f);
00088 
00089   glColor3f(0,0,1);
00090   draw_rect(x+icon_width/2.0f, y+icon_height/2.0f, icon_width/2.0f, icon_height/2.0f);
00091 
00092   glColor3f(1,1,0);
00093   draw_rect(x+icon_width/2.0f, y-icon_height/2.0f, icon_width/2.0f, icon_height/2.0f);
00094 
00095   glColor3f(1,1,1);
00096   glDisable(GL_LINE_STIPPLE);
00097   //glLineWidth(2);
00098 
00099   draw_border(x,y,icon_width, icon_height, 2);
00100 }
00101 
00102 
00103 void vgui_tview_tableau::draw_icons(vgui_tableau_sptr const& parent, float x, float y)
00104 {
00105   vcl_vector<vgui_tableau_sptr> children;
00106   parent->get_children(&children);
00107 
00108   if (children.size() > 0)
00109   {
00110     float ny = y + spacing*children.size(); // fsm; was: y + spacing*children.size()/10;
00111     int num = children.size();
00112 
00113     float total_x = (num-1)*spacing;
00114     float start_x = x - (int) (total_x/2.0f); // why the cast?
00115     float offset_x = 0;
00116 
00117     //glLineStipple (1, 0x0101); // dotted
00118     //glLineStipple (1, 0x00FF); // dashed
00119     //glLineStipple (1, 0x1C47);  // dash/dot/dash
00120     glLineWidth(1);
00121 
00122     int ia = 0;
00123     for (vcl_vector<vgui_tableau_sptr>::iterator i = children.begin();
00124          i != children.end(); ++i, ++ia)
00125     {
00126       glDisable(GL_LINE_STIPPLE);
00127       glColor3f(1,1,1);
00128 
00129       if (parent->type_name() == "vgui_deck_tableau") {
00130         vgui_deck_tableau_sptr deck; deck.vertical_cast(parent);
00131         if (deck->current() != *i) {
00132           glLineStipple (1, 0x1C47);  // dash/dot/dash
00133           glEnable (GL_LINE_STIPPLE);
00134         }
00135       }
00136       else if (parent->type_name() == "vgui_composite_tableau") {
00137         vgui_composite_tableau_sptr comp; comp.vertical_cast(parent);
00138 
00139         if (!comp->is_active(ia)) {
00140           glLineStipple (1, 0x1C47);  // dash/dot/dash
00141           glEnable (GL_LINE_STIPPLE);
00142         }
00143       }
00144       else if (parent->type_name() == "vgui_listmanager2D_tableau") {
00145         vgui_listmanager2D_tableau_sptr lman; lman.vertical_cast(parent);
00146         if (!lman->is_active(ia)) {
00147           if (!lman->is_visible(ia))
00148             glLineStipple (1, 0x0101); // dotted
00149           else
00150             glLineStipple (1, 0x1C47);  // dash/dot/dash
00151           glEnable (GL_LINE_STIPPLE);
00152         }
00153       }
00154 
00155       glLineWidth(1);
00156       glBegin(GL_LINES);
00157       glVertex2f(x,y+icon_height);
00158       glVertex2f(start_x+offset_x,ny-(icon_height));
00159       glEnd();
00160 
00161       if (*i)
00162         draw_icons(*i, start_x+offset_x, ny);
00163       offset_x+=spacing;
00164     }
00165   }
00166 
00167 
00168   if (parent->type_name() == "vgui_tview_tableau") {
00169     draw_tview_icon(x,y);
00170   }
00171   else {
00172     if (parent->type_name() == "vgui_deck_tableau")
00173       glColor3f(0,1,0);
00174     else if (parent->type_name() == "vgui_viewer2D_tableau")
00175       glColor3f(1,0,0);
00176     else if (parent->type_name() == "vgui_viewer3D_tableau")
00177       glColor3f(0, 0, 1);
00178     else if (parent->type_name() == "vgui_displaylist2D_tableau")
00179       glColor3f(0.5, 0, 0);
00180     else if (parent->type_name() == "vgui_displaylist3D_tableau")
00181       glColor3f(0, 0, 0.5);
00182     else if (parent->type_name() == "vgui_listmanager2D_tableau")
00183       glColor3f(1, 0, 0.5);
00184     else if (parent->type_name() == "vgui_composite_tableau")
00185       glColor3f(1, 0, 1);
00186     else if (parent->type_name() == "vgui_image_tableau")
00187       glColor3f(1, 0.5, 0);
00188     else if (parent->type_name() == "vgui_vrml_tableau")
00189       glColor3f(0, 1, 1);
00190     else if (parent->type_name() == "vgui_blackbox_tableau")
00191       glColor3f(0, 0, 0);
00192     else
00193       glColor3f(1,1,0);
00194     draw_tableau_icon(x,y);
00195   }
00196 
00197   if (parent == active_icon) {
00198     glColor3f(1,1,1);
00199     draw_border(x,y,icon_width,icon_height, 6);
00200 
00201     glColor3f(1,0,0);
00202     draw_border(x,y,icon_width,icon_height, 2);
00203   }
00204 }
00205 
00206 
00207 void vgui_tview_tableau::add_icons(vcl_vector<vgui_tview_tableau::icon>* icons, vgui_tableau_sptr const& parent,
00208                                    float x, float y)
00209 {
00210   vcl_vector<vgui_tableau_sptr> children;
00211   parent->get_children(&children);
00212 
00213   if (children.size() > 0)
00214   {
00215     float ny = y + spacing*children.size(); // fsm; was: y + spacing*children.size()/10;
00216     //float ny = y+spacing;
00217     int num = children.size();
00218 
00219     float total_x = (num-1)*spacing;
00220     float start_x = x - (int) (total_x/2.0);
00221     float offset_x = 0;
00222 
00223 
00224     for (vcl_vector<vgui_tableau_sptr>::iterator i = children.begin();
00225          i != children.end(); ++i)
00226     {
00227       add_icons(icons, *i, start_x+offset_x, ny);
00228       offset_x+=spacing;
00229     }
00230   }
00231 
00232   // add this icon
00233   icon this_icon;
00234   this_icon.tableau = parent;
00235   this_icon.x = x;
00236   this_icon.y = y;
00237   icons->push_back(this_icon);
00238 }
00239 
00240 vgui_tableau_sptr vgui_tview_tableau::find_closest_icon(vcl_vector<vgui_tview_tableau::icon> const& icons, float ix, float iy)
00241 {
00242 #ifdef DEBUG
00243   vcl_cerr << "vgui_tview_tableau::find_closest_icon() number of icons = " << icons.size() << '\n';
00244 #endif
00245 
00246   float closest_dist /*quell SunPro warning*/= -1;
00247   vgui_tableau_sptr closest;
00248 
00249   for (vcl_vector<icon>::const_iterator i_iter = icons.begin();
00250        i_iter != icons.end(); ++i_iter) {
00251     icon i = *i_iter;
00252     //hypot(i.x - ix, i.y - iy);
00253     float dx = i.x - ix;
00254     float dy = i.y - iy;
00255     float dist = vcl_sqrt(dx*dx + dy*dy);
00256     if (!closest || dist < closest_dist) {
00257       closest_dist = dist;
00258       closest = i.tableau;
00259     }
00260   }
00261 
00262   return closest;
00263 }
00264 
00265 
00266 vcl_string strip_preceeding_numerals(const char* name)
00267 {
00268   vcl_string str(name);
00269 
00270   vcl_string::iterator s_iter = str.begin();
00271   for (; s_iter != str.end(); ++s_iter) {
00272     if (*s_iter < '0' || *s_iter > '9') {
00273       break;
00274     }
00275   }
00276 
00277   if (s_iter != str.end())
00278     str.erase(str.begin(), s_iter);
00279 
00280   return str;
00281 }
00282 
00283 bool vgui_tview_tableau::handle(const vgui_event& e)
00284 {
00285 #ifdef DEBUG
00286   vcl_cerr << "vgui_tview_tableau::handle\n";
00287 #endif
00288 
00289   GLfloat vp[4];
00290   glGetFloatv(GL_VIEWPORT, vp); // ok
00291   float width = vp[2];
00292   float height = vp[3];
00293 
00294   float startx = width/2;
00295   float starty = height/3;
00296 
00297   if (e.type == vgui_DRAW)
00298   {
00299     // explicitly clearing colour as we do not want colour of
00300     // any tableaux this might be embedded within
00301     glClearColor(0.0, 0.0, 0.0, 1.0);
00302     glClear(GL_COLOR_BUFFER_BIT);
00303 
00304     // draw the child
00305     draw_icons(child, startx, starty);
00306     return true;
00307   }
00308   else if (e.type==vgui_MOTION) {
00309     vcl_vector<icon> icons;
00310     add_icons(&icons, child, startx, starty);
00311 
00312     vgui_projection_inspector pi;
00313     float ix, iy;
00314     pi.window_to_image_coordinates(e.wx, e.wy, ix, iy);
00315 
00316     closest_icon = find_closest_icon(icons, ix, iy);
00317   }
00318   else if (e.type==vgui_BUTTON_DOWN) {
00319     vcl_vector<icon> icons;
00320     add_icons(&icons, child, startx, starty);
00321 
00322     vgui_projection_inspector pi;
00323     float ix, iy;
00324     pi.window_to_image_coordinates(e.wx, e.wy, ix, iy);
00325 
00326     vgui_tableau_sptr t = find_closest_icon(icons, ix, iy);
00327     active_icon = t;
00328 
00329 #ifdef DEBUG
00330     vcl_cerr << "icon is " << (void*) t << '\n';
00331 #endif
00332     if (t) {
00333       vcl_cerr << "---------\n"
00334 #ifdef DEBUG
00335                << "| type : " << strip_preceeding_numerals(typeid(*t).name()) << '\n'
00336 #endif
00337                << "| type_name   : " << t->type_name() << vcl_endl
00338                << "| file_name   : " << t->file_name() << vcl_endl
00339                << "| pretty_name : " << t->pretty_name() << vcl_endl
00340                << "---------\n\n";
00341     }
00342 
00343     post_redraw();
00344   }
00345   else if (e.type==vgui_BUTTON_UP) {
00346     active_icon = 0;
00347     post_redraw();
00348   }
00349   else {
00350     GLint oldbuff;
00351     glGetIntegerv(GL_DRAW_BUFFER, &oldbuff);
00352     glDrawBuffer(GL_NONE);
00353     bool retv = child->handle(e);
00354     glDrawBuffer((GLenum)oldbuff);
00355     return retv;
00356   }
00357 
00358   return false;
00359 }
00360 
00361 
00362 void vgui_tview_tableau::get_popup(const vgui_popup_params& /*params*/, vgui_menu &menu)
00363 {
00364   if (closest_icon) {
00365     menu.separator();
00366     vgui_popup_params np;
00367     np.recurse = false;
00368     closest_icon->get_popup(np, menu);
00369   }
00370 }