/**************************************************************************** GLUI User Interface Toolkit --------------------------- glui_control.cpp - top-level GLUI_Control class -------------------------------------------------- Copyright (c) 1998 Paul Rademacher WWW: http://sourceforge.net/projects/glui/ Forums: http://sourceforge.net/forum/?group_id=92496 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ #include "glui_internal_control.h" int _glui_draw_border_only = 0; /*************************** Drawing Utility routines *********************/ /* Redraw this control. */ void GLUI_Control::redraw(void) { if (glui==NULL || hidden) return; if (glui->should_redraw_now(this)) translate_and_draw_front(); } /** Redraw everybody in our window. */ void GLUI_Control::redraw_window(void) { if (glui==NULL || hidden) return; if ( glui->get_glut_window_id() == -1 ) return; int orig = set_to_glut_window(); glutPostRedisplay(); restore_window(orig); } /* GLUI_Control::translate_and_draw_front() ********/ void GLUI_Control::translate_and_draw_front() { GLUI_DRAWINGSENTINAL_IDIOM glMatrixMode( GL_MODELVIEW ); glPushMatrix(); translate_to_origin(); draw(0,0); glPopMatrix(); } /********** GLUI_Control::set_to_bkgd_color() ********/ void GLUI_Control::set_to_bkgd_color( void ) { if ( NOT glui ) return; glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b ); } /******** GLUI_Control::draw_box_inwards_outline() ********/ void GLUI_Control::draw_box_inwards_outline( int x_min, int x_max, int y_min, int y_max ) { glBegin( GL_LINES ); glColor3f( .5, .5, .5 ); glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min ); glVertex2i( x_min, y_min ); glVertex2i( x_min, y_max ); glColor3f( 1., 1., 1. ); glVertex2i( x_min, y_max ); glVertex2i( x_max, y_max ); glVertex2i( x_max, y_max ); glVertex2i( x_max, y_min ); if ( enabled ) glColor3f( 0., 0., 0. ); else glColor3f( .25, .25, .25 ); glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 ); glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_min+1, y_max-1 ); glColor3f( .75, .75, .75 ); glVertex2i( x_min+1, y_max-1 ); glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_max-1, y_min+1 ); glEnd(); } /******* GLUI_Control::draw_box() **********/ void GLUI_Control::draw_box( int x_min, int x_max, int y_min, int y_max, float r, float g, float b) { if ( r == 1.0 AND g == 1.0 AND b == 1.0 AND NOT enabled AND glui ) { draw_bkgd_box( x_min, x_max, y_min, y_max ); return; } glColor3f( r, g, b ); glBegin( GL_QUADS ); glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min ); glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max ); glEnd(); } /******* GLUI_Control::draw_bkgd_box() **********/ void GLUI_Control::draw_bkgd_box( int x_min, int x_max, int y_min, int y_max ) { set_to_bkgd_color(); glBegin( GL_QUADS ); glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min ); glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max ); glEnd(); } /**** GLUI_Control::draw_active_area() ********/ void GLUI_Control::draw_active_box( int x_min, int x_max, int y_min, int y_max ) { GLUI_DRAWINGSENTINAL_IDIOM if ( active ) { glEnable( GL_LINE_STIPPLE ); glLineStipple( 1, 0x5555 ); glColor3f( 0., 0., 0. ); } else { set_to_bkgd_color(); } glBegin( GL_LINE_LOOP ); glVertex2i(x_min, y_min); glVertex2i( x_max, y_min ); glVertex2i(x_max, y_max); glVertex2i( x_min, y_max ); glEnd(); glDisable( GL_LINE_STIPPLE ); } /**** GLUI_Control::draw_emboss_box() ********/ void GLUI_Control::draw_emboss_box(int x_min,int x_max,int y_min,int y_max) { glLineWidth( 1.0 ); glColor3f( 1.0, 1.0, 1.0 ); glBegin( GL_LINE_LOOP ); glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min ); glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max ); glEnd(); glBegin( GL_LINE_LOOP ); glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 ); glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_min+1, y_max-1 ); glEnd(); glColor3f( .5, .5, .5 ); glBegin( GL_LINE_LOOP ); glVertex2i( x_min, y_min ); glVertex2i( x_max-1, y_min ); glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_min, y_max-1 ); glEnd(); } /******* GLUT_Control::draw_recursive() **********/ void GLUI_Control::draw_recursive( int x, int y ) { GLUI_Control *node; /* printf( "%s %d\n", this->name.c_str(), this->hidden );*/ if ( NOT can_draw() ) return; /*if ( 1 ) { -- Debugging to check control width glColor3f( 1.0, 0.0, 0.0 ); glBegin( GL_LINES ); glVertex2i( x_abs, y_abs );00 glVertex2i( x_abs+w, y_abs ); glEnd(); }*/ glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glTranslatef( (float) this->x_abs + .5, (float) this->y_abs + .5, 0.0 ); if ( NOT _glui_draw_border_only ) { if ( NOT strcmp( name.c_str(), "Rollout" ) ) { } this->draw( this->x_off, this->y_off_top ); } else { if ( this->dynamicCastGLUI_Column() ) { /* printf( "%s w/h: %d/%d\n", (char*) name, w, h ); */ /*w = 2; */ } /* The following draws the area of each control */ glColor3f( 1.0, 0.0, 0.0 ); glBegin( GL_LINE_LOOP ); glVertex2i( 0, 0 ); glVertex2i( w, 0 ); glVertex2i( w, h ); glVertex2i( 0, h ); glEnd(); } glPopMatrix(); node = (GLUI_Control*) first_child(); while( node ) { node->draw_recursive( node->x_abs, node->y_abs ); node = (GLUI_Control*) node->next(); } } /****** GLUI_Control::set_to_glut_window() *********/ /* Sets the current window to the glut window associated with this control */ int GLUI_Control::set_to_glut_window() { int orig_window; if ( NOT glui) return 1; orig_window = glutGetWindow(); glutSetWindow( glui->get_glut_window_id()); return orig_window; } /********** GLUI_Control::restore_window() *********/ void GLUI_Control::restore_window(int orig) { if ( orig > 0 ) glutSetWindow( orig ); } /****************************** Text ***************************/ /*************** GLUI_Control::set_font() **********/ void GLUI_Control::set_font(void *new_font) { font = new_font; redraw(); } /********** GLUI_Control::draw_string() ************/ void GLUI_Control::draw_string( const char *text ) { _glutBitmapString( get_font(), text ); } /**************** GLUI_Control::draw_char() ********/ void GLUI_Control::draw_char(char c) { glutBitmapCharacter( get_font(), c ); } /*********** GLUI_Control::string_width() **********/ int GLUI_Control::string_width(const char *text) { return _glutBitmapWidthString( get_font(), text ); } /************* GLUI_Control::char_width() **********/ int GLUI_Control::char_width(char c) { /* Hash table for faster character width lookups - JVK Speeds up the textbox a little bit. */ int hash_index = c % CHAR_WIDTH_HASH_SIZE; if (char_widths[hash_index][0] != c) { char_widths[hash_index][0] = c; char_widths[hash_index][1] = glutBitmapWidth( get_font(), c ); } return char_widths[hash_index][1]; } /*************** GLUI_Control::get_font() **********/ void *GLUI_Control::get_font( void ) { /*** Does this control have its own font? ***/ if ( this->font != NULL ) return this->font; /*** Does the parent glui have a font? ***/ if ( glui ) return glui->font; /*** Return the default font ***/ return GLUT_BITMAP_HELVETICA_12; } /************* GLUI_Control::draw_name() ***********/ /* This draws the name of the control as either black (if enabled), or */ /* embossed if disabled. */ void GLUI_Control::draw_name(int x, int y) { if ( NOT can_draw() ) return; if ( enabled ) { set_to_bkgd_color(); glRasterPos2i(x+1, y+1); draw_string(name); glColor3b( 0, 0, 0 ); glRasterPos2i(x, y); draw_string(name); } else { /* Control is disabled - emboss the string */ glColor3f( 1.0f, 1.0f, 1.0f ); glRasterPos2i(x+1, y+1); draw_string(name); glColor3f( .4f, .4f, .4f ); glRasterPos2i(x, y); draw_string(name); } } /**************************** Layout and Packing *********************/ /****** GLUI_Control::align() **************/ void GLUI_Control::align() { int col_x, col_y, col_w, col_h, col_x_off, col_y_off; int orig_x_abs; orig_x_abs = x_abs; /* Fix alignment bug relating to columns */ /*return; */ if ( NOT parent() ) return; /* Clearly this shouldn't happen, though */ get_this_column_dims(&col_x, &col_y, &col_w, &col_h, &col_x_off, &col_y_off); if ( this->dynamicCastGLUI_Column() ) { /* if ( this->prev() != NULL ) { ((GLUI_Control*)prev())->get_this_column_dims(&col_x, &col_y, &col_w, &col_h, &col_x_off, &col_y_off); x_abs = col_x + col_w; } else { x_abs = ((GLUI_Control*)parent())->x_abs; } */ return; } if ( alignment == GLUI_ALIGN_LEFT ) { x_abs = col_x + col_x_off; } else if ( alignment == GLUI_ALIGN_RIGHT ) { x_abs = col_x + col_w - col_x_off - this->w; } else if ( alignment == GLUI_ALIGN_CENTER ) { x_abs = col_x + (col_w - this->w) / 2; } if ( this->is_container ) { /*** Shift all child columns ***/ int delta = x_abs - orig_x_abs; GLUI_Control *node; node = (GLUI_Control*) this->first_child(); while( node != NULL ) { if ( node->dynamicCastGLUI_Column() ) { node->x_abs += delta; } node = (GLUI_Control*) node->next(); } } } /************** GLUI_Control::pack() ************/ /* Recalculate positions and offsets */ void GLUI_Control::pack_old(int x, int y) { GLUI_Control *node; int max_w, curr_y, curr_x, max_y; int x_in = x, y_in =y; int x_margin, y_margin_top, y_margin_bot; int y_top_column; int column_x; GLUI_Column *curr_column = NULL; this->update_size(); x_margin = this->x_off; y_margin_top = this->y_off_top; y_margin_bot = this->y_off_bot; this->x_abs = x_in; this->y_abs = y_in; max_w = -1; max_y = -1; curr_x = this->x_abs + x_margin; curr_y = this->y_abs + y_margin_top; /*** Record start of this set of columns ***/ y_top_column = curr_y; column_x = 0; if ( this == glui->main_panel ) { x=x; } /*** Iterate over children, packing them first ***/ node = (GLUI_Control*) this->first_child(); while( node != NULL ) { if ( node->dynamicCastGLUI_Panel() && !node->collapsible) { /* Pad some space above fixed size panels */ curr_y += GLUI_ITEMSPACING; } else if ( node->dynamicCastGLUI_Column()) { curr_column = (GLUI_Column*) node; if ( 1 ) { column_x += max_w + 2 * x_margin; curr_x += max_w + 2 * x_margin; } else { column_x += max_w + 0 * x_margin; curr_x += max_w + 0 * x_margin; } /*node->pack( curr_x, curr_y ); */ node->x_abs = curr_x; node->y_abs = y_top_column; node->w = 2; node->h = curr_y - y_top_column; curr_x += x_margin * 3 + 40; curr_y = y_top_column; max_w = 0; node = (GLUI_Control*) node->next(); continue; } node->pack( curr_x, curr_y ); if ( node->dynamicCastGLUI_Panel() && !node->collapsible) /* Pad some space below fixed size panels */ curr_y += GLUI_ITEMSPACING; curr_y += node->h; if ( node->w > max_w ) { max_w = node->w; if ( curr_column != NULL ) curr_column->w = max_w; } node = (GLUI_Control*) node->next(); if ( node ) { curr_y += GLUI_ITEMSPACING; } if ( curr_y > max_y ) max_y = curr_y; } if ( this->is_container ) { max_y += y_margin_bot; /*** Add bottom border inside box */ if ( this->first_child() ) { if ( this->dynamicCastGLUI_Rollout() ) { /** We don't want the rollout to shrink in width when it's closed **/ this->w = MAX(this->w, column_x + max_w + 2 * x_margin ); } else { this->w = column_x + max_w + 2 * x_margin; } this->h = (max_y - y_in); } else { /* An empty container, so just assign default w & h */ this->w = GLUI_DEFAULT_CONTROL_WIDTH; this->h = GLUI_DEFAULT_CONTROL_HEIGHT; } /** Expand panel if necessary (e.g., to include all the text in a panel label) **/ this->update_size(); } } /*** GLUI_Control::get_this_column_dims() **********/ /* Gets the x,y,w,h,and x/y offsets of the column to which a control belongs */ void GLUI_Control::get_this_column_dims( int *col_x, int *col_y, int *col_w, int *col_h, int *col_x_off, int *col_y_off ) { GLUI_Control *node, *parent_ptr; int parent_h, parent_y_abs; parent_ptr = (GLUI_Control*) parent(); if ( parent_ptr==NULL ) return; parent_h = parent_ptr->h; parent_y_abs = parent_ptr->y_abs; if ( parent_ptr->dynamicCastGLUI_Panel() AND parent_ptr->int_val == GLUI_PANEL_EMBOSSED AND parent_ptr->name != "" ) { parent_h -= GLUI_PANEL_EMBOSS_TOP; parent_y_abs += GLUI_PANEL_EMBOSS_TOP; } if ( 0 ) { GLUI_Node *first, *last, *curr; /** Look for first control in this column **/ first = this; while (first->prev() AND !(first->prev())->dynamicCastGLUI_Column() ) first = first->prev(); /** Look for last control in this column **/ last = this; while ( last->next() AND !(first->next())->dynamicCastGLUI_Column() ) last = last->next(); curr = first; int max_w = -1; do { if ( ((GLUI_Control*)curr)->w > max_w ) max_w = ((GLUI_Control*)curr)->w; if ( curr == last ) break; curr = curr->next(); } while( curr != NULL ); *col_x = ((GLUI_Control*)first)->x_abs; *col_y = ((GLUI_Control*)first)->y_abs; *col_w = max_w; if ( parent() ) { *col_h = ((GLUI_Control*)parent())->h; *col_x_off = ((GLUI_Control*)parent())->x_off; } else { *col_h = 10; *col_x_off = 0; } *col_y_off = 0; return; } if ( 1 ) { /* IS THIS WRONG? */ /*** Look for preceding column ***/ node = (GLUI_Control*) this->prev(); while( node ) { if ( node->dynamicCastGLUI_Column() ) { *col_x = node->x_abs; *col_y = parent_y_abs; *col_w = node->w; *col_h = parent_h; *col_x_off = node->x_off; *col_y_off = 0; return; } node = (GLUI_Control*) node->prev(); } /*** Nope, Look for next column ***/ node = (GLUI_Control*) this->next(); while( node ) { if ( node->dynamicCastGLUI_Column() ) { *col_x = parent_ptr->x_abs; *col_y = parent_y_abs; *col_w = node->x_abs - parent_ptr->x_abs; *col_h = parent_h; *col_x_off = node->x_off; *col_y_off = 0; return; } node = (GLUI_Control*) node->next(); } /*** This is single-column panel, so return panel dims ***/ *col_x = parent_ptr->x_abs; *col_y = parent_y_abs; *col_w = parent_ptr->w; *col_h = parent_h; *col_x_off = parent_ptr->x_off; *col_y_off = 0; } } void GLUI_Control::pack( int x, int y ) { GLUI_Control *node; int max_w, curr_y, curr_x, max_y; int x_in = x, y_in =y; int x_margin, y_margin_top, y_margin_bot; int y_top_column; int column_x; GLUI_Column *curr_column = NULL; this->update_size(); x_margin = this->x_off; y_margin_top = this->y_off_top; y_margin_bot = this->y_off_bot; this->x_abs = x_in; this->y_abs = y_in; max_w = 0; max_y = 0; curr_x = this->x_abs + x_margin; curr_y = this->y_abs + y_margin_top; /*** Record start of this set of columns ***/ y_top_column = curr_y; column_x = curr_x; /*** Iterate over children, packing them first ***/ node = (GLUI_Control*) this->first_child(); while( node != NULL ) { if ( node->dynamicCastGLUI_Panel() && !node->collapsible) { /* Pad some space above fixed-size panels */ curr_y += GLUI_ITEMSPACING; } else if ( node->dynamicCastGLUI_Column() ) { curr_column = (GLUI_Column*) node; curr_x += max_w + 1 * x_margin; column_x = curr_x; node->x_abs = curr_x; node->y_abs = y_top_column; node->w = 2; node->h = curr_y - y_top_column; curr_x += x_margin * 1; curr_y = y_top_column; max_w = 0; node = (GLUI_Control*) node->next(); continue; } node->pack( curr_x, curr_y ); if ( node->dynamicCastGLUI_Panel() && !node->collapsible) /* Pad some space below fixed-size panels */ curr_y += GLUI_ITEMSPACING; curr_y += node->h; if ( node->w > max_w ) { max_w = node->w; if ( curr_column != NULL ) curr_column->w = max_w + x_margin; } if ( curr_y > max_y ) { max_y = curr_y; if ( curr_column != NULL ) curr_column->h = max_y - y_top_column; } node = (GLUI_Control*) node->next(); if ( node ) { curr_y += GLUI_ITEMSPACING; } } if ( this->is_container ) { max_y += y_margin_bot; /*** Add bottom border inside box */ if ( this->first_child() ) { this->w = column_x + max_w + 2 * x_margin - x_in; this->h = (max_y - y_in); } else { /* An empty container, so just assign default w & h */ if ( !this->dynamicCastGLUI_Rollout() && !this->dynamicCastGLUI_Tree() ) { this->w = GLUI_DEFAULT_CONTROL_WIDTH; this->h = GLUI_DEFAULT_CONTROL_HEIGHT; } } /** Expand panel if necessary (e.g., to include all the text in a panel label) **/ this->update_size(); /*** Now we step through the GLUI_Columns, setting the 'h' ***/ node = (GLUI_Control*) this->first_child(); while( node != NULL ) { if ( node->dynamicCastGLUI_Column() ) { node->h = this->h - y_margin_bot - y_margin_top; } node = (GLUI_Control*) node->next(); } } } /******************************** Live Variables **************************/ /*********** GLUI_Control::sync_live() ************/ /* Reads live variable and sets control to its current value */ /* This function is recursive, and operates on control's children */ void GLUI_Control::sync_live(int recurse, int draw_it) { GLUI_Node *node; int sync_it=true; int i; float *fp; bool changed = false; /*** If this is currently active control, and mouse button is down, don't sync ***/ if ( glui ) { if ( this == glui->active_control AND glui->mouse_button_down ) sync_it = false; /*** Actually, just disable syncing if button is down ***/ /*** Nope, go ahead and sync if mouse is down - this allows syncing in callbacks ***/ if ( 0 ) { /* THIS CODE BELOW SHOULD NOT BE EXECUTED */ if ( glui->mouse_button_down ) { /* printf( "Can't sync\n" ); */ return; } } } /*** If this control has a live variable, we check its current value against the stored value in the control ***/ if ( ptr_val != NULL ) { if ( live_type == GLUI_LIVE_NONE OR NOT sync_it ) { } else if ( live_type == GLUI_LIVE_INT ) { if ( *((int*)ptr_val) != last_live_int ) { set_int_val( *((int*)ptr_val) ); last_live_int = *((int*)ptr_val); changed = true; } } else if ( live_type == GLUI_LIVE_FLOAT ) { if ( *((float*)ptr_val) != last_live_float ) { set_float_val( *((float*)ptr_val) ); last_live_float = *((float*)ptr_val); changed = true; } } else if ( live_type == GLUI_LIVE_TEXT ) { if ( last_live_text.compare((const char*)ptr_val) != 0 ) { set_text( (char*) ptr_val ); last_live_text = (const char*)ptr_val; changed = true; } } else if ( live_type == GLUI_LIVE_STRING ) { if ( last_live_text.compare(((std::string*) ptr_val)->c_str()) != 0 ) { set_text( ((std::string*) ptr_val)->c_str()); last_live_text = *((std::string*) ptr_val); changed = true; } } else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) { /*** Step through the arrays, and see if they're the same ***/ fp = (float*) ptr_val; for ( i=0; ifirst_child(); while( node ) { ((GLUI_Control*) node)->sync_live(true, true); node = node->next(); } if ( collapsible == true AND is_open == false ) { /** Here we have a collapsed control (e.g., a rollout that is closed **/ /** We need to go in and sync all the collapsed controls inside **/ node = this->collapsed_node.first_child(); while( node ) { ((GLUI_Control*) node)->sync_live(true, false); node = node->next(); } } } } /********** GLUI_Control::output_live() ************/ /* Writes current value of control to live variable. */ void GLUI_Control::output_live(int update_main_gfx) { int i; float *fp; if ( ptr_val == NULL ) return; if ( NOT live_inited ) return; if ( live_type == GLUI_LIVE_NONE ) { } else if ( live_type == GLUI_LIVE_INT ) { *((int*)ptr_val) = int_val; last_live_int = int_val; } else if ( live_type == GLUI_LIVE_FLOAT ) { *((float*)ptr_val) = float_val; last_live_float = float_val; } else if ( live_type == GLUI_LIVE_TEXT ) { strncpy( (char*) ptr_val, text.c_str(), text.length()+1); last_live_text = text; } else if ( live_type == GLUI_LIVE_STRING ) { (*(std::string*)ptr_val)= text.c_str(); last_live_text = text; } else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) { fp = (float*) ptr_val; for( i=0; iglui != NULL ) { this->glui->post_update_main_gfx(); } } /****** GLUI_Control::execute_callback() **********/ void GLUI_Control::execute_callback() { int old_window; old_window = glutGetWindow(); if ( glui AND glui->main_gfx_window_id != -1 ) glutSetWindow( glui->main_gfx_window_id ); this->callback( this ); // if ( this->callback ) // this->callback( this->user_id ); glutSetWindow( old_window ); } /************** GLUI_Control::init_live() **********/ /* Reads in value of a live variable. Called once, when ctrl is created */ void GLUI_Control::init_live() { int i; float *fp; if ( ptr_val == NULL ) return; if ( live_type == GLUI_LIVE_NONE ) { } else if ( live_type == GLUI_LIVE_INT ) { set_int_val( *((int*)ptr_val) ); last_live_int = *((int*)ptr_val); } else if ( live_type == GLUI_LIVE_FLOAT ) { set_float_val( *((float*)ptr_val) ); last_live_float = *((float*)ptr_val); } else if ( live_type == GLUI_LIVE_TEXT ) { set_text( (const char*) ptr_val ); last_live_text = (const char*) ptr_val; } else if ( live_type == GLUI_LIVE_STRING ) { set_text( ((std::string*) ptr_val)->c_str() ); last_live_text = ((std::string*) ptr_val)->c_str(); } else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) { set_float_array_val( (float*) ptr_val ); fp = (float*) ptr_val; for( i=0; ienable(); node = (GLUI_Control*) node->next(); } } /***** GLUI_Control::disable() ****************/ void GLUI_Control::disable() { GLUI_Control *node; enabled = false; if ( NOT glui ) return; if ( glui->active_control == this ) glui->deactivate_current_control(); redraw(); /*** Now recursively disable all buttons below it ***/ node = (GLUI_Control*) first_child(); while(node) { node->disable(); node = (GLUI_Control*) node->next(); } } /******* GLUI_Control::set_w() **************/ void GLUI_Control::set_w(int new_w) { w = new_w; update_size(); /* Make sure control is big enough to fit text */ if (glui) glui->refresh(); } /**** GLUI_Control::set_h() **************/ void GLUI_Control::set_h(int new_h) { h = new_h; update_size(); /* Make sure control is big enough to fit text */ if (glui) glui->refresh(); } /***** GLUI_Control::set_alignment() ******/ void GLUI_Control::set_alignment(int new_align) { alignment = new_align; if ( glui ) { glui->align_controls(this); redraw_window(); } } /***** GLUI_Control::needs_idle() *********/ /* This method gets overloaded by specific classes, e.g. Spinner. */ /* It returns whether or not a control needs to receive an idle event or not */ /* For example, a spinner only needs idle events when the user is holding */ /* the mouse down in one of the arrows. Otherwise, don't waste cycles */ /* and OpenGL context switching by calling its idle. */ bool GLUI_Control::needs_idle() const { return false; } /********* GLUI_Control::~GLUI_Control() **********/ GLUI_Control::~GLUI_Control() { GLUI_Control *item = (GLUI_Control*) this->first_child(); while (item) { GLUI_Control *tmp = item; item = (GLUI_Control*) item->next(); delete tmp; } } /********* GLUI_Control::hide_internal() ********/ /** Sets hidden==true for this control and all its siblings. */ /** If recurse is true, we go to children as well */ void GLUI_Control::hide_internal( int recurse ) { GLUI_Node *node; node = (GLUI_Node *) this; while( node != NULL ) { ((GLUI_Control*)node)->hidden = true; if ( recurse AND node->first_child() != NULL ) ((GLUI_Control*) node->first_child())->hide_internal(true); node = node->next(); } node = this->collapsed_node.first_child(); while( node != NULL ) { ((GLUI_Control*)node)->hidden = true; if ( recurse AND node->first_child() != NULL ) ((GLUI_Control*) node->first_child())->hide_internal(true); node = node->next(); } } /********* GLUI_Control::unhide_internal() ********/ /** Sets hidden==false for this control and all its siblings. */ /** If recurse is true, we go to children as well */ void GLUI_Control::unhide_internal( int recurse ) { GLUI_Node *node; node = (GLUI_Node *) this; while( node != NULL ) { /* printf( "unhide: %s [%d]\n", ((GLUI_Control*)node)->name.c_str(), ((GLUI_Control*)node)->hidden );*/ ((GLUI_Control*)node)->hidden = false; if ( recurse AND node->first_child() != NULL ) ((GLUI_Control*) node->first_child())->unhide_internal(true); node = node->next(); } node = this->collapsed_node.first_child(); while( node != NULL ) { ((GLUI_Control*)node)->hidden = false; if ( recurse AND node->first_child() != NULL ) ((GLUI_Control*) node->first_child())->unhide_internal(true); node = node->next(); } }