glui_control.cpp
上传用户:gb3593
上传日期:2022-01-07
资源大小:3028k
文件大小:31k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /****************************************************************************
  2.   
  3.   GLUI User Interface Toolkit
  4.   ---------------------------
  5.      glui_control.cpp - top-level GLUI_Control class
  6.           --------------------------------------------------
  7.   Copyright (c) 1998 Paul Rademacher
  8.   WWW:    http://sourceforge.net/projects/glui/
  9.   Forums: http://sourceforge.net/forum/?group_id=92496
  10.   This library is free software; you can redistribute it and/or
  11.   modify it under the terms of the GNU Lesser General Public
  12.   License as published by the Free Software Foundation; either
  13.   version 2.1 of the License, or (at your option) any later version.
  14.   This library is distributed in the hope that it will be useful,
  15.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.   Lesser General Public License for more details.
  18.   You should have received a copy of the GNU Lesser General Public
  19.   License along with this library; if not, write to the Free Software
  20.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21. *****************************************************************************/
  22. #include "glui_internal_control.h"
  23. int _glui_draw_border_only = 0;
  24. /*************************** Drawing Utility routines *********************/
  25. /* Redraw this control. */
  26. void       GLUI_Control::redraw(void) {
  27.     if (glui==NULL || hidden) return;
  28.     if (glui->should_redraw_now(this))
  29.       translate_and_draw_front();
  30. }
  31. /** Redraw everybody in our window. */
  32. void      GLUI_Control::redraw_window(void) {
  33.   if (glui==NULL || hidden) return;
  34.   if ( glui->get_glut_window_id() == -1 ) return;
  35.   int orig = set_to_glut_window();
  36.   glutPostRedisplay();
  37.   restore_window(orig);
  38. }
  39. /* GLUI_Control::translate_and_draw_front() ********/
  40. void GLUI_Control::translate_and_draw_front()
  41. {
  42.   GLUI_DRAWINGSENTINAL_IDIOM
  43.   glMatrixMode( GL_MODELVIEW );
  44.   glPushMatrix();
  45.   translate_to_origin();
  46.   draw(0,0);
  47.   glPopMatrix();
  48. }
  49. /********** GLUI_Control::set_to_bkgd_color() ********/
  50. void GLUI_Control::set_to_bkgd_color( void )
  51. {
  52.   if ( NOT glui )
  53.     return;
  54.   glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b );
  55. }
  56. /******** GLUI_Control::draw_box_inwards_outline() ********/
  57. void GLUI_Control::draw_box_inwards_outline( int x_min, int x_max, int y_min, int y_max )
  58. {
  59.   glBegin( GL_LINES );
  60.   glColor3f( .5, .5, .5 );
  61.   glVertex2i( x_min, y_min );     glVertex2i( x_max, y_min );
  62.   glVertex2i( x_min, y_min );     glVertex2i( x_min, y_max );     
  63.   glColor3f( 1., 1., 1. );
  64.   glVertex2i( x_min, y_max );     glVertex2i( x_max, y_max );
  65.   glVertex2i( x_max, y_max );     glVertex2i( x_max, y_min );
  66.   if ( enabled )
  67.     glColor3f( 0., 0., 0. );
  68.   else
  69.     glColor3f( .25, .25, .25 );
  70.   glVertex2i( x_min+1, y_min+1 );     glVertex2i( x_max-1, y_min+1 );
  71.   glVertex2i( x_min+1, y_min+1 );     glVertex2i( x_min+1, y_max-1 );
  72.   glColor3f( .75, .75, .75 );
  73.   glVertex2i( x_min+1, y_max-1 );     glVertex2i( x_max-1, y_max-1 );
  74.   glVertex2i( x_max-1, y_max-1 );     glVertex2i( x_max-1, y_min+1 );
  75.   glEnd();  
  76. }
  77. /******* GLUI_Control::draw_box() **********/
  78. void GLUI_Control::draw_box( int x_min, int x_max, int y_min, int y_max, float r, float g, float b)
  79. {
  80.   if ( r == 1.0 AND g == 1.0 AND b == 1.0 AND NOT enabled AND glui ) {
  81.     draw_bkgd_box( x_min, x_max, y_min, y_max );
  82.     return;
  83.   }
  84.   glColor3f( r, g, b );
  85.   glBegin( GL_QUADS );
  86.   glVertex2i( x_min, y_min );       glVertex2i( x_max, y_min );
  87.   glVertex2i( x_max, y_max );       glVertex2i( x_min, y_max );
  88.   glEnd();
  89. }
  90. /******* GLUI_Control::draw_bkgd_box() **********/
  91. void GLUI_Control::draw_bkgd_box( int x_min, int x_max, int y_min, int y_max )
  92. {
  93.   set_to_bkgd_color();
  94.   glBegin( GL_QUADS );
  95.   glVertex2i( x_min, y_min );       glVertex2i( x_max, y_min );
  96.   glVertex2i( x_max, y_max );       glVertex2i( x_min, y_max );
  97.   glEnd();
  98. }
  99. /**** GLUI_Control::draw_active_area() ********/
  100. void GLUI_Control::draw_active_box( int x_min, int x_max, int y_min, int y_max )
  101. {
  102.   GLUI_DRAWINGSENTINAL_IDIOM
  103.   if ( active ) {
  104.     glEnable( GL_LINE_STIPPLE );
  105.     glLineStipple( 1, 0x5555 );
  106.     glColor3f( 0., 0., 0. );
  107.   } else {
  108.     set_to_bkgd_color();
  109.   }
  110.   glBegin( GL_LINE_LOOP );
  111.   glVertex2i(x_min, y_min);      glVertex2i( x_max, y_min );
  112.   glVertex2i(x_max, y_max);      glVertex2i( x_min, y_max );
  113.   glEnd();
  114.   
  115.   glDisable( GL_LINE_STIPPLE );
  116. }
  117. /**** GLUI_Control::draw_emboss_box() ********/
  118. void   GLUI_Control::draw_emboss_box(int x_min,int x_max,int y_min,int y_max)
  119. {
  120.   glLineWidth( 1.0 );
  121.   glColor3f( 1.0, 1.0, 1.0 );
  122.   glBegin( GL_LINE_LOOP );
  123.   glVertex2i( x_min, y_min );    glVertex2i( x_max, y_min );
  124.   glVertex2i( x_max, y_max );    glVertex2i( x_min, y_max );
  125.   glEnd();
  126.  
  127.   glBegin( GL_LINE_LOOP );
  128.   glVertex2i( x_min+1, y_min+1 );    glVertex2i( x_max-1, y_min+1 );
  129.   glVertex2i( x_max-1, y_max-1 );    glVertex2i( x_min+1, y_max-1 );
  130.   glEnd();
  131.   
  132.   glColor3f( .5, .5, .5 );
  133.   glBegin( GL_LINE_LOOP );
  134.   glVertex2i( x_min, y_min );
  135.   glVertex2i( x_max-1, y_min );
  136.   glVertex2i( x_max-1, y_max-1 );
  137.   glVertex2i( x_min, y_max-1 );
  138.   glEnd();
  139. }
  140. /******* GLUT_Control::draw_recursive() **********/
  141. void GLUI_Control::draw_recursive( int x, int y )
  142. {
  143.   GLUI_Control *node;
  144.   /*  printf( "%s %dn", this->name.c_str(), this->hidden );*/
  145.   if ( NOT can_draw() )
  146.     return;
  147.   /*if ( 1 ) {  --  Debugging to check control width  
  148.     glColor3f( 1.0, 0.0, 0.0 );
  149.     glBegin( GL_LINES );
  150.     glVertex2i( x_abs, y_abs );00
  151.     glVertex2i( x_abs+w, y_abs );
  152.     glEnd();
  153.     }*/
  154.   glMatrixMode( GL_MODELVIEW );
  155.   glPushMatrix();
  156.   glTranslatef( (float) this->x_abs + .5, 
  157. (float) this->y_abs + .5, 
  158. 0.0 );
  159.   if ( NOT _glui_draw_border_only ) {
  160.     if ( NOT strcmp( name.c_str(), "Rollout" ) ) {
  161.     }
  162.     this->draw( this->x_off, this->y_off_top );
  163.   } 
  164.   else 
  165.   {
  166.     if ( dynamic_cast<GLUI_Column*>(this) ) {
  167.       /*   printf( "%s w/h:   %d/%dn", (char*) name, w, h );              */
  168.       /*w = 2;              */
  169.     }
  170.     /* The following draws the area of each control              */
  171.     glColor3f( 1.0, 0.0, 0.0 );
  172.     glBegin( GL_LINE_LOOP );
  173.     glVertex2i( 0, 0 ); glVertex2i( w, 0 );
  174.     glVertex2i( w, h ); glVertex2i( 0, h );
  175.     glEnd();
  176.   }
  177.   glPopMatrix();
  178.   
  179.   node = (GLUI_Control*) first_child();
  180.   while( node ) {
  181.     node->draw_recursive( node->x_abs, node->y_abs );
  182.     node = (GLUI_Control*) node->next();
  183.   }
  184. }
  185. /****** GLUI_Control::set_to_glut_window() *********/
  186. /*  Sets the current window to the glut window associated with this control  */
  187. int GLUI_Control::set_to_glut_window()
  188. {
  189.   int orig_window;
  190.   if ( NOT glui) 
  191.     return 1;
  192.   orig_window = glutGetWindow();
  193.   glutSetWindow( glui->get_glut_window_id());
  194.   return orig_window;
  195. }
  196. /********** GLUI_Control::restore_window() *********/
  197. void GLUI_Control::restore_window(int orig)
  198. {
  199.   if ( orig > 0 )
  200.     glutSetWindow( orig );
  201. }
  202. /****************************** Text ***************************/
  203. /*************** GLUI_Control::set_font() **********/
  204. void GLUI_Control::set_font(void *new_font)
  205. {
  206.   font = new_font;
  207.   redraw();
  208. }
  209. /********** GLUI_Control::draw_string() ************/
  210. void GLUI_Control::draw_string( const char *text )
  211. {
  212.   _glutBitmapString( get_font(), text );
  213. }
  214. /**************** GLUI_Control::draw_char() ********/
  215. void GLUI_Control::draw_char(char c)
  216. {
  217.   glutBitmapCharacter( get_font(), c );
  218. }
  219. /*********** GLUI_Control::string_width() **********/
  220. int GLUI_Control::string_width(const char *text)
  221. {
  222.   return _glutBitmapWidthString( get_font(), text );
  223. }
  224. /************* GLUI_Control::char_width() **********/
  225. int GLUI_Control::char_width(char c)
  226. { /* Hash table for faster character width lookups - JVK 
  227.        Speeds up the textbox a little bit.
  228.   */
  229.   int hash_index = c % CHAR_WIDTH_HASH_SIZE;
  230.   if (char_widths[hash_index][0] != c) {
  231.     char_widths[hash_index][0] = c;
  232.     char_widths[hash_index][1] = glutBitmapWidth( get_font(), c );
  233.   }
  234.   return char_widths[hash_index][1];
  235. }
  236. /*************** GLUI_Control::get_font() **********/
  237. void *GLUI_Control::get_font( void )
  238. {
  239.   /*** Does this control have its own font? ***/
  240.   if ( this->font != NULL )
  241.     return this->font;
  242.   
  243.   /*** Does the parent glui have a font? ***/
  244.   if ( glui )
  245.     return glui->font;
  246.   /*** Return the default font ***/
  247.   return GLUT_BITMAP_HELVETICA_12;
  248. }
  249. /************* GLUI_Control::draw_name() ***********/
  250. /* This draws the name of the control as either black (if enabled), or       */
  251. /* embossed if disabled.                                                     */
  252. void GLUI_Control::draw_name(int x, int y)
  253. {
  254.   if ( NOT can_draw() )
  255.     return;
  256.   if ( enabled )
  257.   {
  258.     set_to_bkgd_color();
  259.     glRasterPos2i(x+1, y+1);
  260.     draw_string(name);
  261.     glColor3b( 0, 0, 0 );
  262.     glRasterPos2i(x, y);
  263.     draw_string(name);
  264.   }
  265.   else
  266.   {   /* Control is disabled - emboss the string */
  267.     glColor3f( 1.0f, 1.0f, 1.0f );
  268.     glRasterPos2i(x+1, y+1);
  269.     draw_string(name);
  270.     glColor3f( .4f, .4f, .4f );
  271.     glRasterPos2i(x, y);
  272.     draw_string(name);
  273.   }
  274. }
  275. /**************************** Layout and Packing *********************/
  276. /****** GLUI_Control::align() **************/
  277. void GLUI_Control::align()
  278. {
  279.   int  col_x, col_y, col_w, col_h, col_x_off, col_y_off;
  280.   int  orig_x_abs;
  281.   orig_x_abs = x_abs;
  282.   /* Fix alignment bug relating to columns              */
  283.   /*return;              */
  284.   if ( NOT parent() )
  285.     return;  /* Clearly this shouldn't happen, though */
  286.   get_this_column_dims(&col_x, &col_y, &col_w, &col_h, 
  287.        &col_x_off, &col_y_off);
  288.   if ( dynamic_cast<GLUI_Column*>(this) ) {
  289.     /* if ( this->prev() != NULL ) {
  290. ((GLUI_Control*)prev())->get_this_column_dims(&col_x, &col_y, &col_w, &col_h, 
  291. &col_x_off, &col_y_off);
  292. x_abs = col_x + col_w;
  293. }
  294. else {
  295. x_abs = ((GLUI_Control*)parent())->x_abs;
  296. }
  297. */
  298.     return;
  299.   }
  300.   if ( alignment == GLUI_ALIGN_LEFT ) {
  301.     x_abs = col_x + col_x_off;
  302.   }
  303.   else if ( alignment == GLUI_ALIGN_RIGHT ) {
  304.     x_abs = col_x + col_w - col_x_off - this->w;
  305.   }
  306.   else if ( alignment == GLUI_ALIGN_CENTER ) {
  307.     x_abs = col_x + (col_w - this->w) / 2;
  308.   }
  309.   if ( this->is_container ) {
  310.     /***   Shift all child columns   ***/
  311.     int delta = x_abs - orig_x_abs;
  312.     GLUI_Control *node;
  313.     node = (GLUI_Control*) this->first_child();
  314.     while( node != NULL ) {
  315.       if ( dynamic_cast<GLUI_Column*>(node) ) { 
  316. node->x_abs += delta;
  317.       } 
  318.       node = (GLUI_Control*) node->next();
  319.     }
  320.   }
  321. }
  322. /************** GLUI_Control::pack() ************/
  323. /* Recalculate positions and offsets  */
  324. void GLUI_Control::pack_old(int x, int y)
  325. {
  326.   GLUI_Control  *node;
  327.   int            max_w, curr_y, curr_x, max_y;
  328.   int            x_in = x, y_in =y;
  329.   int            x_margin, y_margin_top, y_margin_bot;
  330.   int            y_top_column;
  331.   int            column_x;
  332.   GLUI_Column   *curr_column = NULL;
  333.   this->update_size();
  334.   x_margin     = this->x_off;
  335.   y_margin_top = this->y_off_top;
  336.   y_margin_bot = this->y_off_bot;
  337.   this->x_abs = x_in;
  338.   this->y_abs = y_in;
  339.   max_w  = -1;
  340.   max_y  = -1;
  341.   curr_x = this->x_abs + x_margin;
  342.   curr_y = this->y_abs + y_margin_top;
  343.   /*** Record start of this set of columns ***/
  344.   y_top_column = curr_y;
  345.   column_x     = 0;
  346.   if ( this == glui->main_panel ) {
  347.     x=x;
  348.   }
  349.   /*** Iterate over children, packing them first ***/
  350.   node = (GLUI_Control*) this->first_child();
  351.   while( node != NULL ) {
  352.     if ( dynamic_cast<GLUI_Panel*>(node) && !node->collapsible) { 
  353.       /* Pad some space above fixed size panels */
  354.       curr_y += GLUI_ITEMSPACING;
  355.     } 
  356.     else if ( dynamic_cast<GLUI_Column*>(node)) {
  357.       curr_column = (GLUI_Column*) node;
  358.       if ( 1 ) {
  359. column_x += max_w + 2 * x_margin;
  360. curr_x  += max_w + 2 * x_margin;
  361.       }
  362.       else {
  363. column_x += max_w + 0 * x_margin;
  364. curr_x  += max_w + 0 * x_margin;
  365.       }
  366.       /*node->pack( curr_x, curr_y );              */
  367.       node->x_abs = curr_x;
  368.       node->y_abs = y_top_column;
  369.       node->w     = 2;
  370.       node->h     = curr_y - y_top_column;
  371.       curr_x  += x_margin * 3 + 40;
  372.       curr_y  = y_top_column;
  373.       max_w = 0;
  374.       node = (GLUI_Control*) node->next();
  375.       continue;
  376.     }
  377.     node->pack( curr_x, curr_y );
  378.     if ( dynamic_cast<GLUI_Panel*>(node) && !node->collapsible)  
  379.       /* Pad some space below fixed size panels */
  380.       curr_y += GLUI_ITEMSPACING;
  381.     curr_y  += node->h;
  382.     if ( node->w > max_w ) {
  383.       max_w = node->w;
  384.       if ( curr_column != NULL )
  385. curr_column->w = max_w;
  386.     }
  387.     node = (GLUI_Control*) node->next();
  388.     if ( node ) {
  389.       curr_y += GLUI_ITEMSPACING;
  390.     }
  391.     if ( curr_y > max_y )
  392.       max_y = curr_y;
  393.   }
  394.   if ( this->is_container ) {
  395.     max_y += y_margin_bot;  /*** Add bottom border inside box */
  396.     if ( this->first_child() ) {
  397.       if ( dynamic_cast<GLUI_Rollout*>(this) ) {
  398. /**  We don't want the rollout to shrink in width when it's
  399.   closed **/
  400. this->w = MAX(this->w, column_x + max_w + 2 * x_margin );
  401.       }
  402.       else {
  403. this->w        = column_x + max_w + 2 * x_margin;
  404.       }
  405.       this->h        = (max_y - y_in);
  406.     }
  407.     else  {            /* An empty container, so just assign default w & h */
  408.       this->w        = GLUI_DEFAULT_CONTROL_WIDTH;
  409.       this->h        = GLUI_DEFAULT_CONTROL_HEIGHT;
  410.     }
  411.     /** Expand panel if necessary (e.g., to include all the text in 
  412.       a panel label) **/
  413.     this->update_size();   
  414.   }
  415. }
  416. /*** GLUI_Control::get_this_column_dims() **********/
  417. /* Gets the x,y,w,h,and x/y offsets of the column to which a control belongs */
  418. void    GLUI_Control::get_this_column_dims( int *col_x, int *col_y, 
  419.     int *col_w, int *col_h, 
  420.     int *col_x_off, int *col_y_off )
  421. {
  422.   GLUI_Control *node, *parent_ptr;
  423.   int           parent_h, parent_y_abs;
  424.   parent_ptr = (GLUI_Control*) parent();
  425.   if ( parent_ptr==NULL )
  426.     return;
  427.   parent_h     = parent_ptr->h;
  428.   parent_y_abs = parent_ptr->y_abs;
  429.   
  430.   if ( dynamic_cast<GLUI_Panel*>(parent_ptr) AND
  431.        parent_ptr->int_val == GLUI_PANEL_EMBOSSED AND
  432.        parent_ptr->name != "" ) {
  433.     parent_h -= GLUI_PANEL_EMBOSS_TOP;
  434.     parent_y_abs += GLUI_PANEL_EMBOSS_TOP;
  435.   }
  436.   if ( 0 ) {
  437.     GLUI_Node *first, *last, *curr;
  438.     /**   Look for first control in this column   **/
  439.     first = this;
  440.     while (first->prev() AND !dynamic_cast<GLUI_Column*>(first->prev()) ) 
  441.       first = first->prev();
  442.     /**   Look for last control in this column    **/
  443.     last = this;
  444.     while ( last->next() AND !dynamic_cast<GLUI_Column*>(first->next()) )
  445.       last = last->next();
  446.     curr = first;
  447.     int max_w = -1;
  448.     do {
  449.       if ( ((GLUI_Control*)curr)->w > max_w )
  450. max_w = ((GLUI_Control*)curr)->w;
  451.       if ( curr == last )
  452. break;
  453.       curr = curr->next();
  454.     } while( curr != NULL );
  455.     *col_x     = ((GLUI_Control*)first)->x_abs;
  456.     *col_y     = ((GLUI_Control*)first)->y_abs;
  457.     *col_w     = max_w;
  458.     if ( parent() ) {
  459.       *col_h     = ((GLUI_Control*)parent())->h;
  460.       *col_x_off = ((GLUI_Control*)parent())->x_off;
  461.     }
  462.     else {
  463.       *col_h = 10;
  464.       *col_x_off = 0;
  465.     }
  466.     *col_y_off = 0;
  467.     return;
  468.   }
  469.   if ( 1 ) {    /* IS THIS WRONG? */
  470.     /*** Look for preceding column ***/
  471.     node = (GLUI_Control*) this->prev();
  472.     while( node ) {
  473.       if ( dynamic_cast<GLUI_Column*>(node) ) {
  474. *col_x     = node->x_abs;
  475. *col_y     = parent_y_abs;
  476. *col_w     = node->w;
  477. *col_h     = parent_h;
  478. *col_x_off = node->x_off;
  479. *col_y_off = 0;
  480. return;
  481.       }
  482.       node = (GLUI_Control*) node->prev();
  483.     }
  484.     /*** Nope, Look for next column ***/
  485.     node = (GLUI_Control*) this->next();
  486.     while( node ) {
  487.       if ( dynamic_cast<GLUI_Column*>(node) ) {
  488. *col_x     = parent_ptr->x_abs;
  489. *col_y     = parent_y_abs;
  490. *col_w     = node->x_abs - parent_ptr->x_abs;
  491. *col_h     = parent_h;
  492. *col_x_off = node->x_off;
  493. *col_y_off = 0;
  494. return;
  495.       }
  496.       node = (GLUI_Control*) node->next();
  497.     }
  498.     /***   This is single-column panel, so return panel dims   ***/
  499.     *col_x     = parent_ptr->x_abs;
  500.     *col_y     = parent_y_abs;
  501.     *col_w     = parent_ptr->w;
  502.     *col_h     = parent_h;
  503.     *col_x_off = parent_ptr->x_off;
  504.     *col_y_off = 0;
  505.   }
  506. }
  507. void    GLUI_Control::pack( int x, int y )
  508. {
  509.   GLUI_Control  *node;
  510.   int            max_w, curr_y, curr_x, max_y;
  511.   int            x_in = x, y_in =y;
  512.   int            x_margin, y_margin_top, y_margin_bot;
  513.   int            y_top_column;
  514.   int            column_x;
  515.   GLUI_Column   *curr_column = NULL;
  516.   this->update_size();
  517.   x_margin     = this->x_off;
  518.   y_margin_top = this->y_off_top;
  519.   y_margin_bot = this->y_off_bot;
  520.   
  521.   this->x_abs = x_in;
  522.   this->y_abs = y_in;
  523.   max_w  = 0;
  524.   max_y  = 0;
  525.   curr_x = this->x_abs + x_margin;
  526.   curr_y = this->y_abs + y_margin_top;
  527.   /*** Record start of this set of columns ***/
  528.   y_top_column = curr_y;
  529.   column_x     = curr_x;
  530.   /*** Iterate over children, packing them first ***/
  531.   node = (GLUI_Control*) this->first_child();
  532.   while( node != NULL ) {
  533.     if ( dynamic_cast<GLUI_Panel*>(node) && !node->collapsible) { 
  534.       /* Pad some space above fixed-size panels */
  535.       curr_y += GLUI_ITEMSPACING;
  536.     } 
  537.     else if ( dynamic_cast<GLUI_Column*>(node) ) {
  538.       curr_column = (GLUI_Column*) node;
  539.       curr_x   += max_w + 1 * x_margin;
  540.       column_x  = curr_x;
  541.       node->x_abs = curr_x;
  542.       node->y_abs = y_top_column;
  543.       node->w     = 2;
  544.       node->h     = curr_y - y_top_column;
  545.       curr_x  += x_margin * 1;
  546.       curr_y  = y_top_column;
  547.       max_w = 0;
  548.       node = (GLUI_Control*) node->next();
  549.       continue;
  550.     }
  551.     node->pack( curr_x, curr_y );
  552.     if ( dynamic_cast<GLUI_Panel*>(node)  && !node->collapsible)
  553.       /* Pad some space below fixed-size panels */
  554.       curr_y += GLUI_ITEMSPACING;
  555.     
  556.     curr_y  += node->h;
  557.     if ( node->w > max_w ) {
  558.       max_w = node->w;
  559.       if ( curr_column != NULL )
  560. curr_column->w = max_w + x_margin;
  561.     }
  562.     if ( curr_y > max_y ) {
  563.       max_y = curr_y;
  564.       if ( curr_column != NULL )
  565. curr_column->h = max_y - y_top_column;
  566.     }
  567.     node = (GLUI_Control*) node->next();
  568.     
  569.     if ( node ) {
  570.       curr_y += GLUI_ITEMSPACING;
  571.     }
  572.   }
  573.   if ( this->is_container ) {
  574.     max_y += y_margin_bot;  /*** Add bottom border inside box */
  575.     if ( this->first_child() ) {
  576.       this->w        = column_x + max_w + 2 * x_margin - x_in;
  577.       this->h        = (max_y - y_in);
  578.     }
  579.     else  {            /* An empty container, so just assign default w & h */
  580.       if ( !dynamic_cast<GLUI_Rollout*>(this) &&
  581.            !dynamic_cast<GLUI_Tree*>(this) ) {
  582. this->w        = GLUI_DEFAULT_CONTROL_WIDTH;
  583. this->h        = GLUI_DEFAULT_CONTROL_HEIGHT;
  584.       }
  585.     }
  586.     /** Expand panel if necessary (e.g., to include all the text in 
  587.       a panel label) **/
  588.     this->update_size();   
  589.     /*** Now we step through the GLUI_Columns, setting the 'h'  ***/
  590.     node = (GLUI_Control*) this->first_child();
  591.     while( node != NULL ) {
  592.       if ( dynamic_cast<GLUI_Column*>(node) ) {
  593. node->h = this->h - y_margin_bot - y_margin_top;
  594.       }
  595.       node = (GLUI_Control*) node->next();
  596.     }
  597.   }
  598. }
  599. /******************************** Live Variables **************************/
  600. /*********** GLUI_Control::sync_live() ************/
  601. /* Reads live variable and sets control to its current value                */
  602. /* This function is recursive, and operates on control's children           */
  603. void GLUI_Control::sync_live(int recurse, int draw_it)
  604. {
  605.   GLUI_Node *node;
  606.   int        sync_it=true;
  607.   int        i;
  608.   float      *fp;
  609.   bool       changed = false;
  610.   /*** If this is currently active control, and mouse button is down,
  611.     don't sync ***/
  612.   if ( glui )
  613.   {
  614.     if ( this == glui->active_control AND glui->mouse_button_down )
  615.       sync_it = false;
  616.     /*** Actually, just disable syncing if button is down ***/
  617.     /*** Nope, go ahead and sync if mouse is down - this allows syncing in
  618.       callbacks ***/
  619.     if ( 0 ) { /* THIS CODE BELOW SHOULD NOT BE EXECUTED */
  620.       if ( glui->mouse_button_down ) {
  621. /* printf( "Can't syncn" );              */
  622. return;
  623.       }
  624.     }
  625.   }
  626.   /***  If this control has a live variable, we check its current value
  627.     against the stored value in the control  ***/
  628.   if ( ptr_val != NULL ) {
  629.     if ( live_type == GLUI_LIVE_NONE OR NOT sync_it ) {
  630.     }
  631.     else if ( live_type == GLUI_LIVE_INT ) {
  632.       if ( *((int*)ptr_val) != last_live_int ) {
  633.         set_int_val( *((int*)ptr_val) );
  634.         last_live_int = *((int*)ptr_val);
  635.         changed = true;
  636.       }
  637.     }   
  638.     else if ( live_type == GLUI_LIVE_FLOAT ) {
  639.       if ( *((float*)ptr_val) != last_live_float ) {
  640.         set_float_val( *((float*)ptr_val) );
  641.         last_live_float = *((float*)ptr_val);
  642.         changed = true;
  643.       }
  644.     } 
  645.     else if ( live_type == GLUI_LIVE_TEXT ) {
  646.       if ( last_live_text.compare((const char*)ptr_val) != 0 ) {
  647.         set_text( (char*) ptr_val );
  648.         last_live_text = (const char*)ptr_val;
  649.         changed = true;
  650.       }
  651.     } 
  652.     else if ( live_type == GLUI_LIVE_STRING ) {
  653.       if ( last_live_text.compare(((std::string*) ptr_val)->c_str()) != 0 ) {
  654.         set_text( ((std::string*) ptr_val)->c_str());
  655.         last_live_text = *((std::string*) ptr_val);
  656.         changed = true;
  657.       }
  658.     } 
  659.     else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) { 
  660.       /***  Step through the arrays, and see if they're the same  ***/
  661.       
  662.       fp = (float*) ptr_val;
  663.       for ( i=0; i<float_array_size; i++ ) {
  664.         if ( *fp != last_live_float_array[i] ) {
  665.           changed = true;
  666.           break;
  667.         }
  668.         fp++;
  669.       }
  670.       
  671.       if ( changed == true) {
  672.         fp = (float*) ptr_val;
  673.         set_float_array_val( fp );
  674.         for ( i=0; i<float_array_size; i++ ) {
  675.           last_live_float_array[i] = *fp;
  676.           fp++;
  677.         }
  678.       }
  679.     }
  680.     else if ( live_type == GLUI_LIVE_DOUBLE ) {
  681.     }
  682.   }
  683.   /***  If this control is changed and we're supposed to be drawing, then
  684.     draw it now    ***/
  685.   if ( changed == true AND draw_it ) {
  686.     redraw();
  687.   }
  688.   if ( recurse ) {
  689.     /*** Now recursively output live vars for all children ***/
  690.     node = this->first_child();
  691.     while( node ) {
  692.       ((GLUI_Control*) node)->sync_live(true, true);
  693.       node = node->next();
  694.     }
  695.     if ( collapsible == true AND is_open == false ) {
  696.       /** Here we have a collapsed control (e.g., a rollout that is closed **/
  697.       /** We need to go in and sync all the collapsed controls inside      **/
  698.        
  699.       node = this->collapsed_node.first_child();
  700.       while( node ) {
  701. ((GLUI_Control*) node)->sync_live(true, false);
  702. node = node->next();
  703.       }
  704.     }
  705.   }
  706. }
  707. /********** GLUI_Control::output_live() ************/
  708. /* Writes current value of control to live variable.                         */
  709. void GLUI_Control::output_live(int update_main_gfx)
  710. {
  711.   int    i;
  712.   float *fp;
  713.   if ( ptr_val == NULL )
  714.     return;
  715.    
  716.   if ( NOT live_inited ) 
  717.     return;
  718.    
  719.   if ( live_type == GLUI_LIVE_NONE ) {
  720.   }
  721.   else if ( live_type == GLUI_LIVE_INT ) {
  722.     *((int*)ptr_val) = int_val;
  723.     last_live_int    = int_val;
  724.   } 
  725.   else if ( live_type == GLUI_LIVE_FLOAT ) {
  726.     *((float*)ptr_val) = float_val;
  727.     last_live_float    = float_val;
  728.   } 
  729.   else if ( live_type == GLUI_LIVE_TEXT ) {
  730.     strncpy( (char*) ptr_val, text.c_str(), text.length()+1);
  731.     last_live_text =  text;
  732.   } 
  733.   else if ( live_type == GLUI_LIVE_STRING ) {
  734.     (*(std::string*)ptr_val)= text.c_str();
  735.     last_live_text =  text;
  736.   } 
  737.   else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
  738.     fp = (float*) ptr_val;
  739.     for( i=0; i<float_array_size; i++ ) {
  740.       *fp                      = float_array_val[i];
  741.       last_live_float_array[i] = float_array_val[i];
  742.       fp++;
  743.     }
  744.   }
  745.   else if ( live_type == GLUI_LIVE_DOUBLE ) {
  746.   }
  747.   /** Update the main gfx window? **/
  748.   if ( update_main_gfx AND this->glui != NULL ) {
  749.     this->glui->post_update_main_gfx();
  750.   }
  751. }
  752. /****** GLUI_Control::execute_callback() **********/
  753. void GLUI_Control::execute_callback()
  754. {
  755.   int old_window;
  756.   
  757.   old_window = glutGetWindow();
  758.   if ( glui AND glui->main_gfx_window_id != -1 ) 
  759.     glutSetWindow( glui->main_gfx_window_id );
  760.   this->callback( this );
  761. //  if ( this->callback ) 
  762. //    this->callback( this->user_id );
  763.   glutSetWindow( old_window );
  764. }
  765. /************** GLUI_Control::init_live() **********/
  766. /* Reads in  value of a live variable.  Called once, when ctrl is created   */
  767. void GLUI_Control::init_live()
  768. {
  769.   int    i;
  770.   float *fp;
  771.   if ( ptr_val == NULL )
  772.     return;
  773.   if ( live_type == GLUI_LIVE_NONE ) {
  774.   }
  775.   else if ( live_type == GLUI_LIVE_INT ) {
  776.     set_int_val( *((int*)ptr_val) );
  777.     last_live_int = *((int*)ptr_val);
  778.   } 
  779.   else if ( live_type == GLUI_LIVE_FLOAT ) {
  780.     set_float_val( *((float*)ptr_val) );
  781.     last_live_float = *((float*)ptr_val);
  782.   } 
  783.   else if ( live_type == GLUI_LIVE_TEXT ) {
  784.     set_text( (const char*) ptr_val );
  785.     last_live_text = (const char*) ptr_val;
  786.   }
  787.   else if ( live_type == GLUI_LIVE_STRING ) {
  788.     set_text( ((std::string*) ptr_val)->c_str() );
  789.     last_live_text = ((std::string*) ptr_val)->c_str();
  790.   }
  791.   else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
  792.     set_float_array_val( (float*) ptr_val );
  793.     fp = (float*) ptr_val;
  794.     for( i=0; i<float_array_size; i++ ) {
  795.       last_live_float_array[i] = *fp;
  796.       fp++;
  797.     }
  798.   }
  799.   else if ( live_type == GLUI_LIVE_DOUBLE ) {
  800.   }
  801.   live_inited = true;
  802. }
  803. /***** GLUI_Control::set_float_array_val() ********/
  804. void  GLUI_Control::set_float_array_val( float *array_ptr )
  805. {
  806.   int i;
  807.   if ( array_ptr == NULL )
  808.     return;
  809.   for( i=0; i<float_array_size; i++ ) {
  810.     float_array_val[i] = array_ptr[i];
  811.   }
  812.   /*** Output the live var, without updating the main gfx window ***/
  813.   output_live(false);
  814. }
  815. /***** GLUI_Control::get_float_array_val() ********/
  816. void  GLUI_Control::get_float_array_val( float *array_ptr )
  817. {
  818.   int i;
  819.   if ( array_ptr == NULL )
  820.     return;
  821.   for( i=0; i<float_array_size; i++ ) {
  822.     array_ptr[i] = float_array_val[i];
  823.   }
  824. }
  825. /**************************** Little Utility Routines ********************/
  826. /**** GLUI_Control::set_name() ********************/
  827. void   GLUI_Control::set_name( const char *str )
  828. {
  829.   name = str;
  830.   redraw(); 
  831. }
  832. /**** GLUI_Control::enable() ****************/
  833. void GLUI_Control::enable()
  834. {
  835.   GLUI_Control *node;
  836.   enabled = true;
  837.    
  838.   if ( NOT glui )
  839.     return;
  840.   redraw();
  841.   /*** Now recursively enable all buttons below it ***/
  842.   node = (GLUI_Control*) first_child();
  843.   while(node)
  844.   {
  845.     node->enable();
  846.     node = (GLUI_Control*) node->next();
  847.   }
  848. }
  849. /***** GLUI_Control::disable() ****************/
  850. void GLUI_Control::disable()
  851. {
  852.   GLUI_Control *node;
  853.   enabled = false;
  854.   
  855.   if ( NOT glui )
  856.     return;
  857.   if ( glui->active_control == this )
  858.     glui->deactivate_current_control();
  859.   redraw();
  860.   /*** Now recursively disable all buttons below it ***/
  861.   node = (GLUI_Control*) first_child();
  862.   while(node) {
  863.     node->disable();
  864.     node = (GLUI_Control*) node->next();
  865.   }
  866. }
  867. /******* GLUI_Control::set_w() **************/
  868. void GLUI_Control::set_w(int new_w)
  869. {
  870.   w = new_w;
  871.   update_size();  /* Make sure control is big enough to fit text */
  872.   if (glui) glui->refresh();
  873. }
  874. /**** GLUI_Control::set_h() **************/
  875. void GLUI_Control::set_h(int new_h)
  876. {
  877.   h = new_h;
  878.   update_size();  /* Make sure control is big enough to fit text */
  879.   if (glui) glui->refresh();
  880. }
  881. /***** GLUI_Control::set_alignment() ******/
  882. void GLUI_Control::set_alignment(int new_align)
  883. {
  884.   alignment = new_align;
  885.   if ( glui )
  886.   {
  887.     glui->align_controls(this);
  888.     redraw_window();
  889.   }
  890. }
  891. /***** GLUI_Control::needs_idle() *********/
  892. /* This method gets overloaded by specific classes, e.g. Spinner.            */
  893. /* It returns whether or not a control needs to receive an idle event or not */
  894. /* For example, a spinner only needs idle events when the user is holding    */
  895. /* the mouse down in one of the arrows.  Otherwise, don't waste cycles       */
  896. /* and OpenGL context switching by calling its idle.                         */
  897. bool GLUI_Control::needs_idle() const
  898.   return false; 
  899. }
  900. /********* GLUI_Control::~GLUI_Control() **********/
  901. GLUI_Control::~GLUI_Control()
  902. {
  903.   GLUI_Control *item = (GLUI_Control*) this->first_child();
  904.   while (item) 
  905.   {
  906.     GLUI_Control *tmp = item;
  907.     item = (GLUI_Control*) item->next();
  908.     delete tmp;
  909.   }
  910. }
  911. /********* GLUI_Control::hide_internal() ********/
  912. /** Sets hidden==true for this  control and all its siblings.             */
  913. /**  If recurse is true, we go to children as well                       */
  914. void         GLUI_Control::hide_internal( int recurse )
  915. {
  916.   GLUI_Node *node;
  917.   node = (GLUI_Node *) this;
  918.   while( node != NULL ) {
  919.     ((GLUI_Control*)node)->hidden = true;
  920.     if ( recurse AND node->first_child() != NULL )  
  921.       ((GLUI_Control*) node->first_child())->hide_internal(true);
  922.       
  923.     node = node->next();
  924.   }
  925.   node = this->collapsed_node.first_child();
  926.   while( node != NULL ) {
  927.     ((GLUI_Control*)node)->hidden = true;
  928.     if ( recurse AND node->first_child() != NULL )  
  929.       ((GLUI_Control*) node->first_child())->hide_internal(true);
  930.       
  931.     node = node->next();
  932.   }
  933. }
  934. /********* GLUI_Control::unhide_internal() ********/
  935. /** Sets hidden==false for this  control and all its siblings.             */
  936. /**  If recurse is true, we go to children as well                       */
  937. void         GLUI_Control::unhide_internal( int recurse )
  938. {
  939.   GLUI_Node *node;
  940.   node = (GLUI_Node *) this;
  941.   while( node != NULL ) {
  942.     /*    printf( "unhide: %s [%d]n", ((GLUI_Control*)node)->name.c_str(), 
  943.     ((GLUI_Control*)node)->hidden );*/
  944.     ((GLUI_Control*)node)->hidden = false;
  945.     if ( recurse AND node->first_child() != NULL )  
  946.       ((GLUI_Control*) node->first_child())->unhide_internal(true);
  947.       
  948.     node = node->next();
  949.   }
  950.   node = this->collapsed_node.first_child();
  951.   while( node != NULL ) {
  952.     ((GLUI_Control*)node)->hidden = false;
  953.     if ( recurse AND node->first_child() != NULL )  
  954.       ((GLUI_Control*) node->first_child())->unhide_internal(true);
  955.       
  956.     node = node->next();
  957.   }
  958. }