1 /****************************************************************************
3 GLUI User Interface Toolkit
4 ---------------------------
6 glui_control.cpp - top-level GLUI_Control class
9 --------------------------------------------------
11 Copyright (c) 1998 Paul Rademacher
13 WWW: http://sourceforge.net/projects/glui/
14 Forums: http://sourceforge.net/forum/?group_id=92496
16 This library is free software; you can redistribute it and/or
17 modify it under the terms of the GNU Lesser General Public
18 License as published by the Free Software Foundation; either
19 version 2.1 of the License, or (at your option) any later version.
21 This library is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 Lesser General Public License for more details.
26 You should have received a copy of the GNU Lesser General Public
27 License along with this library; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 *****************************************************************************/
32 #include "glui_internal_control.h"
34 int _glui_draw_border_only = 0;
36 /*************************** Drawing Utility routines *********************/
38 /* Redraw this control. */
39 void GLUI_Control::redraw(void) {
40 if (glui==NULL || hidden) return;
41 if (glui->should_redraw_now(this))
42 translate_and_draw_front();
45 /** Redraw everybody in our window. */
46 void GLUI_Control::redraw_window(void) {
47 if (glui==NULL || hidden) return;
48 if ( glui->get_glut_window_id() == -1 ) return;
49 int orig = set_to_glut_window();
56 /* GLUI_Control::translate_and_draw_front() ********/
58 void GLUI_Control::translate_and_draw_front()
60 GLUI_DRAWINGSENTINAL_IDIOM
62 glMatrixMode( GL_MODELVIEW );
64 translate_to_origin();
70 /********** GLUI_Control::set_to_bkgd_color() ********/
72 void GLUI_Control::set_to_bkgd_color( void )
77 glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b );
80 /******** GLUI_Control::draw_box_inwards_outline() ********/
82 void GLUI_Control::draw_box_inwards_outline( int x_min, int x_max, int y_min, int y_max )
85 glColor3f( .5, .5, .5 );
86 glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
87 glVertex2i( x_min, y_min ); glVertex2i( x_min, y_max );
89 glColor3f( 1., 1., 1. );
90 glVertex2i( x_min, y_max ); glVertex2i( x_max, y_max );
91 glVertex2i( x_max, y_max ); glVertex2i( x_max, y_min );
94 glColor3f( 0., 0., 0. );
96 glColor3f( .25, .25, .25 );
98 glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 );
99 glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_min+1, y_max-1 );
101 glColor3f( .75, .75, .75 );
102 glVertex2i( x_min+1, y_max-1 ); glVertex2i( x_max-1, y_max-1 );
103 glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_max-1, y_min+1 );
108 /******* GLUI_Control::draw_box() **********/
110 void GLUI_Control::draw_box( int x_min, int x_max, int y_min, int y_max, float r, float g, float b)
112 if ( r == 1.0 AND g == 1.0 AND b == 1.0 AND NOT enabled AND glui ) {
113 draw_bkgd_box( x_min, x_max, y_min, y_max );
117 glColor3f( r, g, b );
119 glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
120 glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max );
125 /******* GLUI_Control::draw_bkgd_box() **********/
127 void GLUI_Control::draw_bkgd_box( int x_min, int x_max, int y_min, int y_max )
132 glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
133 glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max );
138 /**** GLUI_Control::draw_active_area() ********/
140 void GLUI_Control::draw_active_box( int x_min, int x_max, int y_min, int y_max )
142 GLUI_DRAWINGSENTINAL_IDIOM
145 glEnable( GL_LINE_STIPPLE );
146 glLineStipple( 1, 0x5555 );
147 glColor3f( 0., 0., 0. );
152 glBegin( GL_LINE_LOOP );
153 glVertex2i(x_min, y_min); glVertex2i( x_max, y_min );
154 glVertex2i(x_max, y_max); glVertex2i( x_min, y_max );
157 glDisable( GL_LINE_STIPPLE );
161 /**** GLUI_Control::draw_emboss_box() ********/
163 void GLUI_Control::draw_emboss_box(int x_min,int x_max,int y_min,int y_max)
166 glColor3f( 1.0, 1.0, 1.0 );
168 glBegin( GL_LINE_LOOP );
169 glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
170 glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max );
173 glBegin( GL_LINE_LOOP );
174 glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 );
175 glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_min+1, y_max-1 );
178 glColor3f( .5, .5, .5 );
179 glBegin( GL_LINE_LOOP );
180 glVertex2i( x_min, y_min );
181 glVertex2i( x_max-1, y_min );
182 glVertex2i( x_max-1, y_max-1 );
183 glVertex2i( x_min, y_max-1 );
189 /******* GLUT_Control::draw_recursive() **********/
191 void GLUI_Control::draw_recursive( int x, int y )
195 /* printf( "%s %d\n", this->name.c_str(), this->hidden );*/
196 if ( NOT can_draw() )
199 /*if ( 1 ) { -- Debugging to check control width
200 glColor3f( 1.0, 0.0, 0.0 );
202 glVertex2i( x_abs, y_abs );00
203 glVertex2i( x_abs+w, y_abs );
208 glMatrixMode( GL_MODELVIEW );
211 glTranslatef( (float) this->x_abs + .5,
212 (float) this->y_abs + .5,
215 if ( NOT _glui_draw_border_only ) {
216 if ( NOT strcmp( name.c_str(), "Rollout" ) ) {
219 this->draw( this->x_off, this->y_off_top );
223 if ( this->dynamicCastGLUI_Column() ) {
224 /* printf( "%s w/h: %d/%d\n", (char*) name, w, h ); */
228 /* The following draws the area of each control */
229 glColor3f( 1.0, 0.0, 0.0 );
230 glBegin( GL_LINE_LOOP );
231 glVertex2i( 0, 0 ); glVertex2i( w, 0 );
232 glVertex2i( w, h ); glVertex2i( 0, h );
237 node = (GLUI_Control*) first_child();
239 node->draw_recursive( node->x_abs, node->y_abs );
240 node = (GLUI_Control*) node->next();
245 /****** GLUI_Control::set_to_glut_window() *********/
246 /* Sets the current window to the glut window associated with this control */
248 int GLUI_Control::set_to_glut_window()
255 orig_window = glutGetWindow();
257 glutSetWindow( glui->get_glut_window_id());
263 /********** GLUI_Control::restore_window() *********/
265 void GLUI_Control::restore_window(int orig)
268 glutSetWindow( orig );
273 /****************************** Text ***************************/
275 /*************** GLUI_Control::set_font() **********/
277 void GLUI_Control::set_font(void *new_font)
284 /********** GLUI_Control::draw_string() ************/
286 void GLUI_Control::draw_string( const char *text )
288 _glutBitmapString( get_font(), text );
292 /**************** GLUI_Control::draw_char() ********/
294 void GLUI_Control::draw_char(char c)
296 glutBitmapCharacter( get_font(), c );
300 /*********** GLUI_Control::string_width() **********/
302 int GLUI_Control::string_width(const char *text)
304 return _glutBitmapWidthString( get_font(), text );
308 /************* GLUI_Control::char_width() **********/
310 int GLUI_Control::char_width(char c)
311 { /* Hash table for faster character width lookups - JVK
312 Speeds up the textbox a little bit.
314 int hash_index = c % CHAR_WIDTH_HASH_SIZE;
315 if (char_widths[hash_index][0] != c) {
316 char_widths[hash_index][0] = c;
317 char_widths[hash_index][1] = glutBitmapWidth( get_font(), c );
319 return char_widths[hash_index][1];
323 /*************** GLUI_Control::get_font() **********/
325 void *GLUI_Control::get_font( void )
327 /*** Does this control have its own font? ***/
328 if ( this->font != NULL )
331 /*** Does the parent glui have a font? ***/
335 /*** Return the default font ***/
336 return GLUT_BITMAP_HELVETICA_12;
340 /************* GLUI_Control::draw_name() ***********/
341 /* This draws the name of the control as either black (if enabled), or */
342 /* embossed if disabled. */
344 void GLUI_Control::draw_name(int x, int y)
346 if ( NOT can_draw() )
352 glRasterPos2i(x+1, y+1);
354 glColor3b( 0, 0, 0 );
359 { /* Control is disabled - emboss the string */
360 glColor3f( 1.0f, 1.0f, 1.0f );
361 glRasterPos2i(x+1, y+1);
363 glColor3f( .4f, .4f, .4f );
370 /**************************** Layout and Packing *********************/
372 /****** GLUI_Control::align() **************/
374 void GLUI_Control::align()
376 int col_x, col_y, col_w, col_h, col_x_off, col_y_off;
381 /* Fix alignment bug relating to columns */
385 return; /* Clearly this shouldn't happen, though */
387 get_this_column_dims(&col_x, &col_y, &col_w, &col_h,
388 &col_x_off, &col_y_off);
390 if ( this->dynamicCastGLUI_Column() ) {
391 /* if ( this->prev() != NULL ) {
392 ((GLUI_Control*)prev())->get_this_column_dims(&col_x, &col_y, &col_w, &col_h,
393 &col_x_off, &col_y_off);
395 x_abs = col_x + col_w;
398 x_abs = ((GLUI_Control*)parent())->x_abs;
404 if ( alignment == GLUI_ALIGN_LEFT ) {
405 x_abs = col_x + col_x_off;
407 else if ( alignment == GLUI_ALIGN_RIGHT ) {
408 x_abs = col_x + col_w - col_x_off - this->w;
410 else if ( alignment == GLUI_ALIGN_CENTER ) {
411 x_abs = col_x + (col_w - this->w) / 2;
414 if ( this->is_container ) {
415 /*** Shift all child columns ***/
416 int delta = x_abs - orig_x_abs;
420 node = (GLUI_Control*) this->first_child();
421 while( node != NULL ) {
422 if ( node->dynamicCastGLUI_Column() ) {
423 node->x_abs += delta;
426 node = (GLUI_Control*) node->next();
433 /************** GLUI_Control::pack() ************/
434 /* Recalculate positions and offsets */
436 void GLUI_Control::pack_old(int x, int y)
439 int max_w, curr_y, curr_x, max_y;
440 int x_in = x, y_in =y;
441 int x_margin, y_margin_top, y_margin_bot;
444 GLUI_Column *curr_column = NULL;
446 x_margin = this->x_off;
447 y_margin_top = this->y_off_top;
448 y_margin_bot = this->y_off_bot;
453 curr_x = this->x_abs + x_margin;
454 curr_y = this->y_abs + y_margin_top;
455 /*** Record start of this set of columns ***/
456 y_top_column = curr_y;
458 if ( this == glui->main_panel ) {
461 /*** Iterate over children, packing them first ***/
462 node = (GLUI_Control*) this->first_child();
463 while( node != NULL ) {
464 if ( node->dynamicCastGLUI_Panel() && !node->collapsible) {
465 /* Pad some space above fixed size panels */
466 curr_y += GLUI_ITEMSPACING;
468 else if ( node->dynamicCastGLUI_Column()) {
469 curr_column = (GLUI_Column*) node;
471 column_x += max_w + 2 * x_margin;
472 curr_x += max_w + 2 * x_margin;
475 column_x += max_w + 0 * x_margin;
476 curr_x += max_w + 0 * x_margin;
478 /*node->pack( curr_x, curr_y ); */
479 node->x_abs = curr_x;
480 node->y_abs = y_top_column;
482 node->h = curr_y - y_top_column;
483 curr_x += x_margin * 3 + 40;
484 curr_y = y_top_column;
486 node = (GLUI_Control*) node->next();
489 node->pack( curr_x, curr_y );
490 if ( node->dynamicCastGLUI_Panel() && !node->collapsible)
491 /* Pad some space below fixed size panels */
492 curr_y += GLUI_ITEMSPACING;
494 if ( node->w > max_w ) {
496 if ( curr_column != NULL )
497 curr_column->w = max_w;
499 node = (GLUI_Control*) node->next();
501 curr_y += GLUI_ITEMSPACING;
503 if ( curr_y > max_y )
506 if ( this->is_container ) {
507 max_y += y_margin_bot; /*** Add bottom border inside box */
508 if ( this->first_child() ) {
509 if ( this->dynamicCastGLUI_Rollout() ) {
510 /** We don't want the rollout to shrink in width when it's
512 this->w = MAX(this->w, column_x + max_w + 2 * x_margin );
515 this->w = column_x + max_w + 2 * x_margin;
517 this->h = (max_y - y_in);
519 else { /* An empty container, so just assign default w & h */
520 this->w = GLUI_DEFAULT_CONTROL_WIDTH;
521 this->h = GLUI_DEFAULT_CONTROL_HEIGHT;
523 /** Expand panel if necessary (e.g., to include all the text in
529 /*** GLUI_Control::get_this_column_dims() **********/
530 /* Gets the x,y,w,h,and x/y offsets of the column to which a control belongs */
532 void GLUI_Control::get_this_column_dims( int *col_x, int *col_y,
533 int *col_w, int *col_h,
534 int *col_x_off, int *col_y_off )
536 GLUI_Control *node, *parent_ptr;
537 int parent_h, parent_y_abs;
539 parent_ptr = (GLUI_Control*) parent();
541 if ( parent_ptr==NULL )
544 parent_h = parent_ptr->h;
545 parent_y_abs = parent_ptr->y_abs;
547 if ( parent_ptr->dynamicCastGLUI_Panel() AND
548 parent_ptr->int_val == GLUI_PANEL_EMBOSSED AND
549 parent_ptr->name != "" ) {
550 parent_h -= GLUI_PANEL_EMBOSS_TOP;
551 parent_y_abs += GLUI_PANEL_EMBOSS_TOP;
555 GLUI_Node *first, *last, *curr;
557 /** Look for first control in this column **/
559 while (first->prev() AND !(first->prev())->dynamicCastGLUI_Column() )
560 first = first->prev();
562 /** Look for last control in this column **/
564 while ( last->next() AND !(first->next())->dynamicCastGLUI_Column() )
570 if ( ((GLUI_Control*)curr)->w > max_w )
571 max_w = ((GLUI_Control*)curr)->w;
577 } while( curr != NULL );
579 *col_x = ((GLUI_Control*)first)->x_abs;
580 *col_y = ((GLUI_Control*)first)->y_abs;
583 *col_h = ((GLUI_Control*)parent())->h;
584 *col_x_off = ((GLUI_Control*)parent())->x_off;
595 if ( 1 ) { /* IS THIS WRONG? */
596 /*** Look for preceding column ***/
597 node = (GLUI_Control*) this->prev();
599 if ( node->dynamicCastGLUI_Column() ) {
600 *col_x = node->x_abs;
601 *col_y = parent_y_abs;
604 *col_x_off = node->x_off;
610 node = (GLUI_Control*) node->prev();
613 /*** Nope, Look for next column ***/
614 node = (GLUI_Control*) this->next();
616 if ( node->dynamicCastGLUI_Column() ) {
617 *col_x = parent_ptr->x_abs;
618 *col_y = parent_y_abs;
619 *col_w = node->x_abs - parent_ptr->x_abs;
621 *col_x_off = node->x_off;
627 node = (GLUI_Control*) node->next();
630 /*** This is single-column panel, so return panel dims ***/
631 *col_x = parent_ptr->x_abs;
632 *col_y = parent_y_abs;
633 *col_w = parent_ptr->w;
635 *col_x_off = parent_ptr->x_off;
641 void GLUI_Control::pack( int x, int y )
644 int max_w, curr_y, curr_x, max_y;
645 int x_in = x, y_in =y;
646 int x_margin, y_margin_top, y_margin_bot;
649 GLUI_Column *curr_column = NULL;
653 x_margin = this->x_off;
654 y_margin_top = this->y_off_top;
655 y_margin_bot = this->y_off_bot;
662 curr_x = this->x_abs + x_margin;
663 curr_y = this->y_abs + y_margin_top;
665 /*** Record start of this set of columns ***/
667 y_top_column = curr_y;
670 /*** Iterate over children, packing them first ***/
672 node = (GLUI_Control*) this->first_child();
673 while( node != NULL ) {
674 if ( node->dynamicCastGLUI_Panel() && !node->collapsible) {
675 /* Pad some space above fixed-size panels */
676 curr_y += GLUI_ITEMSPACING;
678 else if ( node->dynamicCastGLUI_Column() ) {
679 curr_column = (GLUI_Column*) node;
680 curr_x += max_w + 1 * x_margin;
683 node->x_abs = curr_x;
684 node->y_abs = y_top_column;
686 node->h = curr_y - y_top_column;
688 curr_x += x_margin * 1;
689 curr_y = y_top_column;
692 node = (GLUI_Control*) node->next();
696 node->pack( curr_x, curr_y );
698 if ( node->dynamicCastGLUI_Panel() && !node->collapsible)
699 /* Pad some space below fixed-size panels */
700 curr_y += GLUI_ITEMSPACING;
704 if ( node->w > max_w ) {
706 if ( curr_column != NULL )
707 curr_column->w = max_w + x_margin;
710 if ( curr_y > max_y ) {
712 if ( curr_column != NULL )
713 curr_column->h = max_y - y_top_column;
716 node = (GLUI_Control*) node->next();
719 curr_y += GLUI_ITEMSPACING;
724 if ( this->is_container ) {
725 max_y += y_margin_bot; /*** Add bottom border inside box */
727 if ( this->first_child() ) {
728 this->w = column_x + max_w + 2 * x_margin - x_in;
729 this->h = (max_y - y_in);
731 else { /* An empty container, so just assign default w & h */
732 if ( !this->dynamicCastGLUI_Rollout() &&
733 !this->dynamicCastGLUI_Tree() ) {
734 this->w = GLUI_DEFAULT_CONTROL_WIDTH;
735 this->h = GLUI_DEFAULT_CONTROL_HEIGHT;
739 /** Expand panel if necessary (e.g., to include all the text in
744 /*** Now we step through the GLUI_Columns, setting the 'h' ***/
745 node = (GLUI_Control*) this->first_child();
746 while( node != NULL ) {
747 if ( node->dynamicCastGLUI_Column() ) {
748 node->h = this->h - y_margin_bot - y_margin_top;
751 node = (GLUI_Control*) node->next();
758 /******************************** Live Variables **************************/
759 /*********** GLUI_Control::sync_live() ************/
760 /* Reads live variable and sets control to its current value */
761 /* This function is recursive, and operates on control's children */
763 void GLUI_Control::sync_live(int recurse, int draw_it)
769 bool changed = false;
771 /*** If this is currently active control, and mouse button is down,
775 if ( this == glui->active_control AND glui->mouse_button_down )
778 /*** Actually, just disable syncing if button is down ***/
779 /*** Nope, go ahead and sync if mouse is down - this allows syncing in
781 if ( 0 ) { /* THIS CODE BELOW SHOULD NOT BE EXECUTED */
782 if ( glui->mouse_button_down ) {
783 /* printf( "Can't sync\n" ); */
789 /*** If this control has a live variable, we check its current value
790 against the stored value in the control ***/
792 if ( ptr_val != NULL ) {
793 if ( live_type == GLUI_LIVE_NONE OR NOT sync_it ) {
795 else if ( live_type == GLUI_LIVE_INT ) {
796 if ( *((int*)ptr_val) != last_live_int ) {
797 set_int_val( *((int*)ptr_val) );
798 last_live_int = *((int*)ptr_val);
802 else if ( live_type == GLUI_LIVE_FLOAT ) {
803 if ( *((float*)ptr_val) != last_live_float ) {
804 set_float_val( *((float*)ptr_val) );
805 last_live_float = *((float*)ptr_val);
809 else if ( live_type == GLUI_LIVE_TEXT ) {
810 if ( last_live_text.compare((const char*)ptr_val) != 0 ) {
811 set_text( (char*) ptr_val );
812 last_live_text = (const char*)ptr_val;
816 else if ( live_type == GLUI_LIVE_STRING ) {
817 if ( last_live_text.compare(((std::string*) ptr_val)->c_str()) != 0 ) {
818 set_text( ((std::string*) ptr_val)->c_str());
819 last_live_text = *((std::string*) ptr_val);
823 else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
824 /*** Step through the arrays, and see if they're the same ***/
826 fp = (float*) ptr_val;
827 for ( i=0; i<float_array_size; i++ ) {
828 if ( *fp != last_live_float_array[i] ) {
836 if ( changed == true) {
837 fp = (float*) ptr_val;
838 set_float_array_val( fp );
839 for ( i=0; i<float_array_size; i++ ) {
840 last_live_float_array[i] = *fp;
845 else if ( live_type == GLUI_LIVE_DOUBLE ) {
849 /*** If this control is changed and we're supposed to be drawing, then
851 if ( changed == true AND draw_it ) {
856 /*** Now recursively output live vars for all children ***/
857 node = this->first_child();
859 ((GLUI_Control*) node)->sync_live(true, true);
863 if ( collapsible == true AND is_open == false ) {
864 /** Here we have a collapsed control (e.g., a rollout that is closed **/
865 /** We need to go in and sync all the collapsed controls inside **/
867 node = this->collapsed_node.first_child();
869 ((GLUI_Control*) node)->sync_live(true, false);
877 /********** GLUI_Control::output_live() ************/
878 /* Writes current value of control to live variable. */
880 void GLUI_Control::output_live(int update_main_gfx)
885 if ( ptr_val == NULL )
888 if ( NOT live_inited )
891 if ( live_type == GLUI_LIVE_NONE ) {
893 else if ( live_type == GLUI_LIVE_INT ) {
894 *((int*)ptr_val) = int_val;
895 last_live_int = int_val;
897 else if ( live_type == GLUI_LIVE_FLOAT ) {
898 *((float*)ptr_val) = float_val;
899 last_live_float = float_val;
901 else if ( live_type == GLUI_LIVE_TEXT ) {
902 strncpy( (char*) ptr_val, text.c_str(), text.length()+1);
903 last_live_text = text;
905 else if ( live_type == GLUI_LIVE_STRING ) {
906 (*(std::string*)ptr_val)= text.c_str();
907 last_live_text = text;
909 else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
910 fp = (float*) ptr_val;
912 for( i=0; i<float_array_size; i++ ) {
913 *fp = float_array_val[i];
914 last_live_float_array[i] = float_array_val[i];
918 else if ( live_type == GLUI_LIVE_DOUBLE ) {
921 /** Update the main gfx window? **/
922 if ( update_main_gfx AND this->glui != NULL ) {
923 this->glui->post_update_main_gfx();
928 /****** GLUI_Control::execute_callback() **********/
930 void GLUI_Control::execute_callback()
934 old_window = glutGetWindow();
936 if ( glui AND glui->main_gfx_window_id != -1 )
937 glutSetWindow( glui->main_gfx_window_id );
939 this->callback( this );
940 // if ( this->callback )
941 // this->callback( this->user_id );
943 glutSetWindow( old_window );
947 /************** GLUI_Control::init_live() **********/
948 /* Reads in value of a live variable. Called once, when ctrl is created */
950 void GLUI_Control::init_live()
955 if ( ptr_val == NULL )
958 if ( live_type == GLUI_LIVE_NONE ) {
960 else if ( live_type == GLUI_LIVE_INT ) {
961 set_int_val( *((int*)ptr_val) );
962 last_live_int = *((int*)ptr_val);
964 else if ( live_type == GLUI_LIVE_FLOAT ) {
965 set_float_val( *((float*)ptr_val) );
966 last_live_float = *((float*)ptr_val);
968 else if ( live_type == GLUI_LIVE_TEXT ) {
969 set_text( (const char*) ptr_val );
970 last_live_text = (const char*) ptr_val;
972 else if ( live_type == GLUI_LIVE_STRING ) {
973 set_text( ((std::string*) ptr_val)->c_str() );
974 last_live_text = ((std::string*) ptr_val)->c_str();
976 else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
977 set_float_array_val( (float*) ptr_val );
979 fp = (float*) ptr_val;
981 for( i=0; i<float_array_size; i++ ) {
982 last_live_float_array[i] = *fp;
987 else if ( live_type == GLUI_LIVE_DOUBLE ) {
993 /***** GLUI_Control::set_float_array_val() ********/
995 void GLUI_Control::set_float_array_val( float *array_ptr )
999 if ( array_ptr == NULL )
1002 for( i=0; i<float_array_size; i++ ) {
1003 float_array_val[i] = array_ptr[i];
1006 /*** Output the live var, without updating the main gfx window ***/
1011 /***** GLUI_Control::get_float_array_val() ********/
1013 void GLUI_Control::get_float_array_val( float *array_ptr )
1017 if ( array_ptr == NULL )
1020 for( i=0; i<float_array_size; i++ ) {
1021 array_ptr[i] = float_array_val[i];
1027 /**************************** Little Utility Routines ********************/
1029 /**** GLUI_Control::set_name() ********************/
1031 void GLUI_Control::set_name( const char *str )
1037 /**** GLUI_Control::enable() ****************/
1039 void GLUI_Control::enable()
1050 /*** Now recursively enable all buttons below it ***/
1051 node = (GLUI_Control*) first_child();
1055 node = (GLUI_Control*) node->next();
1060 /***** GLUI_Control::disable() ****************/
1062 void GLUI_Control::disable()
1071 if ( glui->active_control == this )
1072 glui->deactivate_current_control();
1075 /*** Now recursively disable all buttons below it ***/
1076 node = (GLUI_Control*) first_child();
1079 node = (GLUI_Control*) node->next();
1083 /******* GLUI_Control::set_w() **************/
1085 void GLUI_Control::set_w(int new_w)
1088 update_size(); /* Make sure control is big enough to fit text */
1089 if (glui) glui->refresh();
1093 /**** GLUI_Control::set_h() **************/
1095 void GLUI_Control::set_h(int new_h)
1098 update_size(); /* Make sure control is big enough to fit text */
1099 if (glui) glui->refresh();
1103 /***** GLUI_Control::set_alignment() ******/
1105 void GLUI_Control::set_alignment(int new_align)
1107 alignment = new_align;
1111 glui->align_controls(this);
1117 /***** GLUI_Control::needs_idle() *********/
1118 /* This method gets overloaded by specific classes, e.g. Spinner. */
1119 /* It returns whether or not a control needs to receive an idle event or not */
1120 /* For example, a spinner only needs idle events when the user is holding */
1121 /* the mouse down in one of the arrows. Otherwise, don't waste cycles */
1122 /* and OpenGL context switching by calling its idle. */
1124 bool GLUI_Control::needs_idle() const
1130 /********* GLUI_Control::~GLUI_Control() **********/
1132 GLUI_Control::~GLUI_Control()
1134 GLUI_Control *item = (GLUI_Control*) this->first_child();
1138 GLUI_Control *tmp = item;
1139 item = (GLUI_Control*) item->next();
1144 /********* GLUI_Control::hide_internal() ********/
1145 /** Sets hidden==true for this control and all its siblings. */
1146 /** If recurse is true, we go to children as well */
1148 void GLUI_Control::hide_internal( int recurse )
1152 node = (GLUI_Node *) this;
1153 while( node != NULL ) {
1154 ((GLUI_Control*)node)->hidden = true;
1156 if ( recurse AND node->first_child() != NULL )
1157 ((GLUI_Control*) node->first_child())->hide_internal(true);
1159 node = node->next();
1162 node = this->collapsed_node.first_child();
1163 while( node != NULL ) {
1164 ((GLUI_Control*)node)->hidden = true;
1166 if ( recurse AND node->first_child() != NULL )
1167 ((GLUI_Control*) node->first_child())->hide_internal(true);
1169 node = node->next();
1174 /********* GLUI_Control::unhide_internal() ********/
1175 /** Sets hidden==false for this control and all its siblings. */
1176 /** If recurse is true, we go to children as well */
1178 void GLUI_Control::unhide_internal( int recurse )
1182 node = (GLUI_Node *) this;
1183 while( node != NULL ) {
1184 /* printf( "unhide: %s [%d]\n", ((GLUI_Control*)node)->name.c_str(),
1185 ((GLUI_Control*)node)->hidden );*/
1186 ((GLUI_Control*)node)->hidden = false;
1188 if ( recurse AND node->first_child() != NULL )
1189 ((GLUI_Control*) node->first_child())->unhide_internal(true);
1191 node = node->next();
1194 node = this->collapsed_node.first_child();
1195 while( node != NULL ) {
1196 ((GLUI_Control*)node)->hidden = false;
1198 if ( recurse AND node->first_child() != NULL )
1199 ((GLUI_Control*) node->first_child())->unhide_internal(true);
1201 node = node->next();