1 /****************************************************************************
2
3 GLUI User Interface Toolkit (LGPL)
4 ---------------------------
5
6 glui.cpp
7
8 --------------------------------------------------
9
10 Copyright (c) 1998 Paul Rademacher
11
12 WWW: http://sourceforge.net/projects/glui/
13 Forums: http://sourceforge.net/forum/?group_id=92496
14
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either
18 version 2.1 of the License, or (at your option) any later version.
19
20 This library is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public
26 License along with this library; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
29 *****************************************************************************/
30 #include "glui_internal_control.h"
31
32
33 /**
34 Note: moving this routine here from glui_add_controls.cpp prevents the linker
35 from touching glui_add_controls.o in non-deprecated programs, which
36 descreases the linked size of small GLUI programs substantially (100K+). (OSL 2006/06)
37 */
add_child_to_control(GLUI_Node * parent,GLUI_Control * child)38 void GLUI_Node::add_child_to_control(GLUI_Node *parent,GLUI_Control *child)
39 {
40 GLUI_Control *parent_control;
41
42 /*** Collapsible nodes have to be handled differently, b/c the first and
43 last children are swapped in and out ***/
44 parent_control = ((GLUI_Control*)parent);
45 if ( parent_control->collapsible == true ) {
46 if ( NOT parent_control->is_open ) {
47 /** Swap in the original first and last children **/
48 parent_control->child_head = parent_control->collapsed_node.child_head;
49 parent_control->child_tail = parent_control->collapsed_node.child_tail;
50
51 /*** Link this control ***/
52 child->link_this_to_parent_last( parent_control );
53
54 /** Swap the children back out ***/
55 parent_control->collapsed_node.child_head = parent_control->child_head;
56 parent_control->collapsed_node.child_tail = parent_control->child_tail;
57 parent_control->child_head = NULL;
58 parent_control->child_tail = NULL;
59 }
60 else {
61 child->link_this_to_parent_last( parent_control );
62 }
63 }
64 else {
65 child->link_this_to_parent_last( parent_control );
66 }
67 child->glui = (GLUI*) parent_control->glui;
68 child->update_size();
69 child->enabled = parent_control->enabled;
70 child->glui->refresh();
71
72 /** Now set the 'hidden' var based on the parent **/
73 if ( parent_control->hidden OR
74 (parent_control->collapsible AND NOT parent_control->is_open ) )
75 {
76 child->hidden = true;
77 }
78 }
79
80
81 /************************************ GLUI_Node::add_control() **************/
82
add_control(GLUI_Control * child)83 int GLUI_Node::add_control( GLUI_Control *child )
84 {
85 add_child_to_control(this,child);
86 return true;
87 }
88
89 /************************************ GLUI_Main::add_control() **************/
90
add_control(GLUI_Node * parent,GLUI_Control * control)91 int GLUI_Main::add_control( GLUI_Node *parent, GLUI_Control *control )
92 {
93 add_child_to_control(parent,control);
94 return true;
95 }
96
97
98
99 /*** This object must be used to create a GLUI ***/
100
101 GLUI_Master_Object GLUI_Master;
102
103 /************************************ finish_drawing() ***********
104 Probably a silly routine. Called after all event handling callbacks.
105 */
106
finish_drawing(void)107 static void finish_drawing(void)
108 {
109 glFinish();
110 }
111
112 /************************************ GLUI_CB::operator()() ************/
operator ()(GLUI_Control * ctrl) const113 void GLUI_CB::operator()(GLUI_Control*ctrl) const
114 {
115 if (idCB) idCB(ctrl->user_id);
116 if (objCB) objCB(ctrl);
117 }
118
119
120 /************************************************ GLUI::GLUI() **********/
121
init(const char * text,long flags,int x,int y,int parent_window)122 int GLUI::init( const char *text, long flags, int x, int y, int parent_window )
123 {
124 int old_glut_window;
125
126 this->flags = flags;
127
128 window_name = text;
129
130 buffer_mode = buffer_back; ///< New smooth way
131 //buffer_mode = buffer_front; ///< Old flickery way (a bit faster).
132
133 /*** We copy over the current window callthroughs ***/
134 /*** (I think this might actually only be needed for subwindows) ***/
135 /* glut_keyboard_CB = GLUI_Master.glut_keyboard_CB;
136 glut_reshape_CB = GLUI_Master.glut_reshape_CB;
137 glut_special_CB = GLUI_Master.glut_special_CB;
138 glut_mouse_CB = GLUI_Master.glut_mouse_CB;*/
139
140
141 if ( (flags & GLUI_SUBWINDOW) != GLUI_SUBWINDOW ) { /* not a subwindow, creating a new top-level window */
142 old_glut_window = glutGetWindow();
143
144 create_standalone_window( window_name.c_str(), x, y );
145 setup_default_glut_callbacks();
146
147 if ( old_glut_window > 0 )
148 glutSetWindow( old_glut_window );
149
150 top_level_glut_window_id = glut_window_id;
151 }
152 else /* *is* a subwindow */
153 {
154 old_glut_window = glutGetWindow();
155
156 create_subwindow( parent_window, flags );
157 setup_default_glut_callbacks();
158
159 if ( old_glut_window > 0 )
160 glutSetWindow( old_glut_window );
161
162 top_level_glut_window_id = parent_window;
163
164 /*
165 glutReshapeFunc( glui_parent_window_reshape_func );
166 glutSpecialFunc( glui_parent_window_special_func );
167 glutKeyboardFunc( glui_parent_window_keyboard_func );
168 glutMouseFunc( glui_parent_window_mouse_func );
169 */
170
171 }
172
173 return true;
174 }
175
176
177 /**************************** GLUI_Main::create_standalone_window() ********/
178
create_standalone_window(const char * name,int x,int y)179 void GLUI_Main::create_standalone_window( const char *name, int x, int y )
180 {
181 glutInitWindowSize( 100, 100 );
182 if ( x >= 0 OR y >= 0 )
183 glutInitWindowPosition( x, y );
184 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
185 glut_window_id = glutCreateWindow( name );
186 }
187
188
189 /******************************** GLUI_Main::create_subwindow() **********/
190
create_subwindow(int parent_window,int window_alignment)191 void GLUI_Main::create_subwindow( int parent_window, int window_alignment )
192 {
193 glut_window_id = glutCreateSubWindow(parent_window, 0,0, 100, 100);
194 this->parent_window = parent_window;
195 }
196
197
198 /**************************** GLUI_Main::setup_default_glut_callbacks() *****/
199
setup_default_glut_callbacks(void)200 void GLUI_Main::setup_default_glut_callbacks( void )
201 {
202 glutDisplayFunc( glui_display_func );
203 glutReshapeFunc( glui_reshape_func );
204 glutKeyboardFunc( glui_keyboard_func );
205 glutSpecialFunc( glui_special_func );
206 glutMouseFunc( glui_mouse_func );
207 glutMotionFunc( glui_motion_func );
208 glutPassiveMotionFunc( glui_passive_motion_func );
209 glutEntryFunc( glui_entry_func );
210 glutVisibilityFunc( glui_visibility_func );
211 /* glutIdleFunc( glui_idle_func ); // FIXME! 100% CPU usage! */
212 }
213
214
215 /********************************************** glui_display_func() ********/
216
glui_display_func(void)217 void glui_display_func(void)
218 {
219 GLUI *glui;
220
221 /* printf( "display func\n" ); */
222
223 glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
224
225 if ( glui ) {
226 glui->display();
227 /*
228 Do not do anything after the above line, b/c the GLUI
229 window might have just closed itself
230 */
231 }
232 }
233
234
235 /********************************************** glui_reshape_func() ********/
236
glui_reshape_func(int w,int h)237 void glui_reshape_func(int w,int h )
238 {
239 GLUI *glui;
240 GLUI_Glut_Window *glut_window;
241 int current_window;
242
243 /*printf( "glui_reshape_func(): %d w/h: %d/%d\n", glutGetWindow(), w, h ); */
244
245 current_window = glutGetWindow();
246
247 /*** First check if this is main glut window ***/
248 glut_window = GLUI_Master.find_glut_window( current_window );
249 if ( glut_window ) {
250 if (glut_window->glut_reshape_CB) glut_window->glut_reshape_CB(w,h);
251
252 /*** Now send reshape events to all subwindows ***/
253 glui = (GLUI*) GLUI_Master.gluis.first_child();
254 while(glui) {
255 if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
256 glui->parent_window == current_window ) {
257 glutSetWindow( glui->get_glut_window_id());
258 glui->reshape(w,h);
259 /* glui->check_subwindow_position(); */
260 }
261 glui = (GLUI*) glui->next();
262 }
263 }
264 else {
265 /*** A standalone GLUI window ***/
266
267 glui = GLUI_Master.find_glui_by_window_id( current_window );
268
269 if ( glui ) {
270 glui->reshape(w,h);
271 }
272 }
273 }
274
275 /********************************************** glui_keyboard_func() ********/
276
glui_keyboard_func(unsigned char key,int x,int y)277 void glui_keyboard_func(unsigned char key, int x, int y)
278 {
279 GLUI *glui;
280 int current_window;
281 GLUI_Glut_Window *glut_window;
282
283 current_window = glutGetWindow();
284 glut_window = GLUI_Master.find_glut_window( current_window );
285
286 /*printf( "key: %d\n", current_window ); */
287
288 if ( glut_window ) { /** Was event in a GLUT window? **/
289 if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) {
290 glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
291
292 GLUI_Master.active_control_glui->keyboard(key,x,y);
293 finish_drawing();
294
295 glutSetWindow( current_window );
296 }
297 else {
298 if (glut_window->glut_keyboard_CB)
299 glut_window->glut_keyboard_CB( key, x, y );
300 }
301 }
302 else { /*** Nope, event was in a standalone GLUI window **/
303 glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
304
305 if ( glui ) {
306 glui->keyboard(key,x,y);
307 finish_drawing();
308 }
309 }
310 }
311
312
313
314
glui_special_up_func(int key,int x,int y)315 void glui_special_up_func(int key, int x, int y)
316 {
317 GLUI *glui;
318 int current_window;
319 GLUI_Glut_Window *glut_window;
320
321 current_window = glutGetWindow();
322 glut_window = GLUI_Master.find_glut_window( current_window );
323
324 if (glut_window) /** Was event in a GLUT window? **/
325 {
326 if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control )
327 {
328 glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
329
330 GLUI_Master.active_control_glui->special_up(key,x,y);
331 finish_drawing();
332
333 glutSetWindow( current_window );
334 }
335 else
336 {
337 if (glut_window->glut_special_up_CB)
338 glut_window->glut_special_up_CB( key, x, y );
339 }
340 }
341 else /*** Nope, event was in a standalone GLUI window **/
342 {
343 glui = GLUI_Master.find_glui_by_window_id(glutGetWindow());
344
345 if ( glui )
346 {
347 glui->special_up(key,x,y);
348 finish_drawing();
349 }
350 }
351 }
352
353
354
355 /************************************************ glui_special_func() ********/
356
glui_special_func(int key,int x,int y)357 void glui_special_func(int key, int x, int y)
358 {
359 GLUI *glui;
360 int current_window;
361 GLUI_Glut_Window *glut_window;
362
363 current_window = glutGetWindow();
364 glut_window = GLUI_Master.find_glut_window( current_window );
365
366 if (glut_window) /** Was event in a GLUT window? **/
367 {
368 if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control )
369 {
370 glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
371
372 GLUI_Master.active_control_glui->special(key,x,y);
373 finish_drawing();
374
375 glutSetWindow( current_window );
376 }
377 else
378 {
379 if (glut_window->glut_special_CB)
380 glut_window->glut_special_CB( key, x, y );
381 }
382 }
383 else /*** Nope, event was in a standalone GLUI window **/
384 {
385 glui = GLUI_Master.find_glui_by_window_id(glutGetWindow());
386
387 if ( glui )
388 {
389 glui->special(key,x,y);
390 finish_drawing();
391 }
392 }
393 }
394
395 /********************************************** glui_mouse_func() ********/
396
glui_mouse_func(int button,int state,int x,int y)397 void glui_mouse_func(int button, int state, int x, int y)
398 {
399 GLUI *glui;
400 int current_window;
401 GLUI_Glut_Window *glut_window;
402
403 current_window = glutGetWindow();
404 glut_window = GLUI_Master.find_glut_window( current_window );
405
406 if ( glut_window ) { /** Was event in a GLUT window? **/
407 if ( GLUI_Master.active_control_glui != NULL )
408 GLUI_Master.active_control_glui->deactivate_current_control();
409
410 if (glut_window->glut_mouse_CB)
411 glut_window->glut_mouse_CB( button, state, x, y );
412 finish_drawing();
413 }
414 else { /** Nope - event was in a GLUI standalone window **/
415 glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
416 if ( glui ) {
417 glui->passive_motion( 0,0 );
418 glui->mouse( button, state, x, y );
419 finish_drawing();
420 }
421 }
422 }
423
424
425 /********************************************** glui_motion_func() ********/
426
glui_motion_func(int x,int y)427 void glui_motion_func(int x, int y)
428 {
429 GLUI *glui;
430
431 glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
432
433 if ( glui ) {
434 glui->motion(x,y);
435 finish_drawing();
436 }
437
438 }
439
440
441 /**************************************** glui_passive_motion_func() ********/
442
glui_passive_motion_func(int x,int y)443 void glui_passive_motion_func(int x, int y)
444 {
445 GLUI *glui;
446
447 glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
448
449 if ( glui ) {
450 glui->passive_motion(x,y);
451 finish_drawing();
452 }
453 }
454
455
456 /********************************************** glui_entry_func() ********/
457
glui_entry_func(int state)458 void glui_entry_func(int state)
459 {
460 GLUI *glui;
461
462 glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
463
464 if ( glui ) {
465 glui->entry(state);
466 }
467 }
468
469
470 /******************************************** glui_visibility_func() ********/
471
glui_visibility_func(int state)472 void glui_visibility_func(int state)
473 {
474 GLUI *glui;
475
476 /* printf( "IN GLUI VISIBILITY()\n" ); */
477 /* fflush( stdout ); */
478
479 glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
480
481 if ( glui ) {
482 glui->visibility(state);
483 }
484 }
485
486
487 /********************************************** glui_idle_func() ********/
488 /* Send idle event to each glui, then to the main window */
489
glui_idle_func(void)490 void glui_idle_func(void)
491 {
492 GLUI *glui;
493
494 glui = (GLUI*) GLUI_Master.gluis.first_child();
495 while( glui ) {
496 glui->idle();
497 finish_drawing();
498
499 glui = (GLUI*) glui->next();
500 }
501
502 if ( GLUI_Master.glut_idle_CB ) {
503 /*** We set the current glut window before calling the user's
504 idle function, even though glut explicitly says the window id is
505 undefined in an idle callback. ***/
506
507 /** Check what the current window is first ***/
508
509 /*** Arbitrarily set the window id to the main gfx window of the
510 first glui window ***/
511 /* int current_window, new_window; */
512 /* current_window = glutGetWindow(); */
513 /* if (GLUI_Master.gluis.first_child() != NULL ) { */
514 /* new_window = ((GLUI_Main*)GLUI_Master.gluis.first_child())-> */
515 /* main_gfx_window_id; */
516 /* if ( new_window > 0 AND new_window != old_window ) { */
517 /* --- Window is changed only if its not already the current window ---*/
518 /* glutSetWindow( new_window ); */
519 /* } */
520 /*} */
521
522 GLUI_Master.glut_idle_CB();
523 }
524 }
525
526 /*********************************** GLUI_Master_Object::GLUI_Master_Object() ******/
527
GLUI_Master_Object()528 GLUI_Master_Object::GLUI_Master_Object()
529 : glui_id_counter(1),
530 glut_idle_CB(NULL)
531 {
532 }
533
~GLUI_Master_Object()534 GLUI_Master_Object::~GLUI_Master_Object()
535 {
536 }
537
538 /*********************************** GLUI_Master_Object::create_glui() ******/
539
create_glui(const char * name,long flags,int x,int y)540 GLUI *GLUI_Master_Object::create_glui( const char *name, long flags,int x,int y )
541 {
542 GLUI *new_glui = new GLUI;
543 new_glui->init( name, flags, x, y, -1 );
544 new_glui->link_this_to_parent_last( &this->gluis );
545 return new_glui;
546 }
547
548
549 /************************** GLUI_Master_Object::create_glui_subwindow() ******/
550
create_glui_subwindow(int parent_window,long flags)551 GLUI *GLUI_Master_Object::create_glui_subwindow( int parent_window,
552 long flags )
553 {
554 GLUI *new_glui = new GLUI;
555 GLUI_String new_name;
556 glui_format_str( new_name, "subwin_%p", this );
557
558 new_glui->init( new_name.c_str(), flags | GLUI_SUBWINDOW, 0,0,
559 parent_window );
560 new_glui->main_panel->set_int_val( GLUI_PANEL_EMBOSSED );
561 new_glui->link_this_to_parent_last( &this->gluis );
562 return new_glui;
563 }
564
565
566 /********************** GLUI_Master_Object::find_glui_by_window_id() ********/
567
find_glui_by_window_id(int window_id)568 GLUI *GLUI_Master_Object::find_glui_by_window_id( int window_id )
569 {
570 GLUI_Node *node;
571
572 node = gluis.first_child();
573 while( node ) {
574 if ( ((GLUI*)node)->get_glut_window_id() == window_id )
575 return (GLUI*) node;
576
577 node = node->next();
578 }
579 return NULL;
580 }
581
582
583 /******************************************** GLUI_Main::display() **********/
584
display(void)585 void GLUI_Main::display( void )
586 {
587 int win_w, win_h;
588
589 /* SUBTLE: on freeGLUT, the correct window is always already set.
590 But older versions of GLUT need this call, or else subwindows
591 don't update properly when resizing or damage-painting.
592 */
593 glutSetWindow( glut_window_id );
594
595 /* Set up OpenGL state for widget drawing */
596 glDisable( GL_DEPTH_TEST );
597 glCullFace( GL_BACK );
598 glDisable( GL_CULL_FACE );
599 glDisable( GL_LIGHTING );
600 set_current_draw_buffer();
601
602 /**** This function is used as a special place to do 'safe' processing,
603 e.g., handling window close requests.
604 That is, we can't close the window directly in the callback, so
605 we set a flag, post a redisplay message (which eventually calls
606 this function), then close the window safely in here. ****/
607 if ( closing ) {
608 close_internal();
609 return;
610 }
611
612 /* if ( TEST_AND( this->flags, GLUI_SUBWINDOW ))
613 check_subwindow_position();
614 */
615
616 win_w = glutGet( GLUT_WINDOW_WIDTH );
617 win_h = glutGet( GLUT_WINDOW_HEIGHT );
618
619 /*** Check here if the window needs resizing ***/
620 if ( win_w != main_panel->w OR win_h != main_panel->h ) {
621 glutReshapeWindow( main_panel->w, main_panel->h );
622 return;
623 }
624
625 /******* Draw GLUI window ******/
626 glClearColor( (float) bkgd_color.r / 255.0,
627 (float) bkgd_color.g / 255.0,
628 (float) bkgd_color.b / 255.0,
629 1.0 );
630 glClear( GL_COLOR_BUFFER_BIT ); /* | GL_DEPTH_BUFFER_BIT ); */
631
632 set_ortho_projection();
633
634 glMatrixMode( GL_MODELVIEW );
635 glLoadIdentity();
636
637 /*** Rotate image so y increases downward.
638 In normal OpenGL, y increases upward. ***/
639 glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 );
640 glRotatef( 180.0, 0.0, 1.0, 0.0 );
641 glRotatef( 180.0, 0.0, 0.0, 1.0 );
642 glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 );
643
644 // Recursively draw the main panel
645 // main_panel->draw_bkgd_box( 0, 0, win_w, win_h );
646 main_panel->draw_recursive( 0, 0 );
647
648 switch (buffer_mode) {
649 case buffer_front: /* Make sure drawing gets to screen */
650 glFlush();
651 break;
652 case buffer_back: /* Bring back buffer to front */
653 glutSwapBuffers();
654 break;
655 }
656 }
657
658
659
660
661 /*************************************** _glutBitmapWidthString() **********/
662
_glutBitmapWidthString(void * font,const char * s)663 int _glutBitmapWidthString( void *font, const char *s )
664 {
665 const char *p = s;
666 int width = 0;
667
668 while( *p != '\0' ) {
669 width += glutBitmapWidth( font, *p );
670 p++;
671 }
672
673 return width;
674 }
675
676 /************************************ _glutBitmapString *********************/
677 /* Displays the contents of a string using GLUT's bitmap character function */
678 /* Does not handle newlines */
679
_glutBitmapString(void * font,const char * s)680 void _glutBitmapString( void *font, const char *s )
681 {
682 const char *p = s;
683
684 while( *p != '\0' ) {
685 glutBitmapCharacter( font, *p );
686 p++;
687 }
688 }
689
690
691
692 /****************************** GLUI_Main::reshape() **************/
693
reshape(int reshape_w,int reshape_h)694 void GLUI_Main::reshape( int reshape_w, int reshape_h )
695 {
696 int new_w, new_h;
697
698 pack_controls();
699
700 new_w = main_panel->w;/* + 1; */
701 new_h = main_panel->h;/* + 1; */
702
703 if ( reshape_w != new_w OR reshape_h != new_h ) {
704 this->w = new_w;
705 this->h = new_h;
706
707 glutReshapeWindow( new_w, new_h );
708 }
709 else {
710 }
711
712 if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
713 check_subwindow_position();
714
715 /***** if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
716 }
717 else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
718 }
719 else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
720 }
721 else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
722 }
723 ****/
724 }
725
726 glViewport( 0, 0, new_w, new_h );
727
728 /* printf( "%d: %d\n", glutGetWindow(), this->flags ); */
729
730 glutPostRedisplay();
731 }
732
733
734 /****************************** GLUI_Main::keyboard() **************/
735
keyboard(unsigned char key,int x,int y)736 void GLUI_Main::keyboard(unsigned char key, int x, int y)
737 {
738 GLUI_Control *new_control;
739
740 curr_modifiers = glutGetModifiers();
741
742 /*** If it's a tab or shift tab, we don't pass it on to the controls.
743 Instead, we use it to cycle through active controls ***/
744 if ( key == '\t' AND !mouse_button_down AND
745 (!active_control || !active_control->wants_tabs())) {
746 if ( curr_modifiers & GLUT_ACTIVE_SHIFT ) {
747 new_control = find_prev_control( active_control );
748 }
749 else {
750 new_control = find_next_control( active_control );
751 }
752
753 /* if ( new_control )
754 printf( "new_control: %s\n", new_control->name );
755 */
756
757 deactivate_current_control();
758 activate_control( new_control, GLUI_ACTIVATE_TAB );
759 }
760 else if ( key == ' ' AND active_control
761 AND active_control->spacebar_mouse_click ) {
762 /*** If the user presses the spacebar, and a non-edittext control
763 is active, we send it a mouse down event followed by a mouse up
764 event (simulated mouse-click) ***/
765
766 active_control->mouse_down_handler( 0, 0 );
767 active_control->mouse_up_handler( 0, 0, true );
768 } else {
769 /*** Pass the keystroke onto the active control, if any ***/
770 if ( active_control != NULL )
771 active_control->key_handler( key, curr_modifiers );
772 }
773 }
774
775
776
special_up(int key,int x,int y)777 void GLUI_Main::special_up(int key, int x, int y)
778 {
779 curr_modifiers = glutGetModifiers();
780
781 /*** Pass the keystroke onto the active control, if any ***/
782 if ( active_control != NULL )
783 active_control->special_up_handler( key, glutGetModifiers() );
784 }
785
786
787 /****************************** GLUI_Main::special() **************/
788
special(int key,int x,int y)789 void GLUI_Main::special(int key, int x, int y)
790 {
791 curr_modifiers = glutGetModifiers();
792
793 /*** Pass the keystroke onto the active control, if any ***/
794 if ( active_control != NULL )
795 active_control->special_handler( key, glutGetModifiers() );
796 }
797
798
799
800 /****************************** GLUI_Main::mouse() **************/
801
mouse(int button,int state,int x,int y)802 void GLUI_Main::mouse(int button, int state, int x, int y)
803 {
804 int callthrough;
805 GLUI_Control *control;
806
807 /* printf( "MOUSE: %d %d\n", button, state ); */
808
809 callthrough = true;
810
811 curr_modifiers = glutGetModifiers();
812
813 if ( button == GLUT_LEFT ) {
814 control = find_control( x, y );
815
816 /*if ( control ) printf( "control: %s\n", control->name.c_str() ); */
817
818 if ( mouse_button_down AND active_control != NULL AND
819 state == GLUT_UP )
820 {
821 /** We just released the mouse, which was depressed at some control **/
822
823 callthrough = active_control->
824 mouse_up_handler( x, y, control==active_control);
825 glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
826
827 if ( active_control AND
828 active_control->active_type == GLUI_CONTROL_ACTIVE_MOUSEDOWN AND 0)
829 {
830 /*** This is a control that needs to be deactivated when the
831 mouse button is released ****/
832 deactivate_current_control();
833 }
834 }
835 else {
836 if ( control ) {
837 if ( NOT mouse_button_down AND state == GLUT_DOWN ) {
838 /*** We just pressed the mouse down at some control ***/
839
840 if ( active_control != control ) {
841 if ( active_control != NULL ) {
842 /** There is an active control still - deactivate it ***/
843 deactivate_current_control();
844 }
845 }
846
847 if ( control->enabled ) {
848 activate_control( control, GLUI_ACTIVATE_MOUSE );
849 callthrough = control->mouse_down_handler( x, y );
850 }
851 }
852 }
853 }
854
855 if ( state == GLUT_DOWN )
856 mouse_button_down = true;
857 else if ( state == GLUT_UP )
858 mouse_button_down = false;
859 }
860
861 /**
862 NO CALLTHROUGH NEEDED FOR MOUSE EVENTS
863 if ( callthrough AND glut_mouse_CB )
864 glut_mouse_CB( button, state, x, y );
865 **/
866
867 callthrough=callthrough; /* To get rid of compiler warnings */
868 }
869
870
871 /****************************** GLUI_Main::motion() **************/
872
motion(int x,int y)873 void GLUI_Main::motion(int x, int y)
874 {
875 int callthrough;
876 GLUI_Control *control;
877
878 /* printf( "MOTION: %d %d\n", x, y ); */
879
880 callthrough = true;
881
882 control = find_control(x,y);
883
884 if ( mouse_button_down AND active_control != NULL ) {
885 callthrough =
886 active_control->mouse_held_down_handler(x,y,control==active_control);
887 }
888
889 /**
890 NO CALLTHROUGH NEEDED FOR MOUSE EVENTS
891
892 if ( callthrough AND glut_motion_CB )
893 glut_motion_CB(x,y);
894 **/
895
896 callthrough=callthrough; /* To get rid of compiler warnings */
897 }
898
899
900 /*********************** GLUI_Main::passive_motion() **************/
901
passive_motion(int x,int y)902 void GLUI_Main::passive_motion(int x, int y)
903 {
904 GLUI_Control *control;
905
906 control = find_control( x, y );
907
908 /* printf( "%p %p\n", control, mouse_over_control ); */
909
910 if ( control != mouse_over_control ) {
911 if ( mouse_over_control ) {
912 mouse_over_control->mouse_over( false, x, y );
913 }
914
915 if ( control ) {
916 control->mouse_over( true, x, y );
917 mouse_over_control = control;
918 }
919 }
920
921 /*
922 if ( curr_cursor != GLUT_CURSOR_INHERIT ) {
923 curr_cursor = GLUT_CURSOR_INHERIT;
924 glutSetCursor( GLUT_CURSOR_INHERIT );
925 }*/
926
927 }
928
929
930 /****************************** GLUI_Main::entry() **************/
931
entry(int state)932 void GLUI_Main::entry(int state)
933 {
934 /*if ( NOT active_control OR ( active_control AND ( active_control->type == GLUI_CONTROL_EDITTEXT
935 OR active_control->type == GLUI_CONTROL_SPINNER) ) )*/
936 glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
937 }
938
939
940 /****************************** GLUI_Main::visibility() **************/
941
visibility(int state)942 void GLUI_Main::visibility(int state)
943 {
944 }
945
946
947 /****************************** GLUI_Main::idle() **************/
948
idle(void)949 void GLUI_Main::idle(void)
950 {
951 /*** Pass the idle event onto the active control, if any ***/
952
953 /* printf( "IDLE \t" ); */
954
955 if ( active_control != NULL ) {
956 /* First we check if the control actually needs the idle right now.
957 Otherwise, let's avoid wasting cycles and OpenGL context switching */
958
959 if ( active_control->needs_idle() ) {
960 /*** Set the current glut window to the glui window */
961 /*** But don't change the window if we're already at that window ***/
962
963 if ( glut_window_id > 0 AND glutGetWindow() != glut_window_id ) {
964 glutSetWindow( glut_window_id );
965 }
966
967 active_control->idle();
968 }
969 }
970 }
971
needs_idle(void)972 int GLUI_Main::needs_idle( void )
973 {
974 return active_control != NULL && active_control->needs_idle();
975 }
976
977
978 /******************************************* GLUI_Main::find_control() ******/
979
find_control(int x,int y)980 GLUI_Control *GLUI_Main::find_control( int x, int y )
981 {
982 GLUI_Control *node, *last_container;
983
984 last_container = NULL;
985
986 node = main_panel;
987 while( node != NULL ) {
988 if ( !node->dynamicCastGLUI_Column() AND
989 PT_IN_BOX( x, y,
990 node->x_abs, node->x_abs + node->w,
991 node->y_abs, node->y_abs + node->h )
992 )
993 {
994 /*** Point is inside current node ***/
995
996 if ( node->first_child() == NULL ) {
997 /*** SPECIAL CASE: for edittext boxes, we make sure click is
998 in box, and not on name string. This should be generalized
999 for all controls later... ***/
1000 if ( node->dynamicCastGLUI_EditText() ) {
1001 if ( x < node->x_abs + ((GLUI_EditText*)node)->text_x_offset )
1002 return (GLUI_Control*) node->parent();
1003 }
1004
1005 return node; /* point is inside this node, and node has no children,
1006 so return this node as the selected node */
1007 }
1008 else {
1009 /*** This is a container class ***/
1010 last_container = node;
1011 node = (GLUI_Control*) node->first_child(); /* Descend into child */
1012 }
1013
1014 }
1015 else {
1016 node = (GLUI_Control*) node->next();
1017 }
1018 }
1019
1020 /** No leaf-level nodes found to accept the mouse click, so
1021 return the last container control found which DOES accept the click **/
1022
1023 if ( last_container ) {
1024 /* printf( "ctrl: '%s'\n", last_container->name ); */
1025
1026 return last_container;
1027 }
1028 else {
1029 return NULL;
1030 }
1031 }
1032
1033
1034 /************************************* GLUI_Main::pack_controls() ***********/
1035
pack_controls(void)1036 void GLUI_Main::pack_controls( void )
1037 {
1038 main_panel->pack(0,0);
1039
1040 /**** Now align controls within their bounds ****/
1041 align_controls( main_panel );
1042
1043 /*** If this is a subwindow, expand panel to fit parent window ***/
1044 if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
1045 int parent_h, parent_w;
1046 int orig_window;
1047
1048 orig_window = glutGetWindow();
1049 glutSetWindow( this->top_level_glut_window_id );
1050 parent_h = glutGet( GLUT_WINDOW_HEIGHT );
1051 parent_w = glutGet( GLUT_WINDOW_WIDTH );
1052
1053 glutSetWindow( orig_window );
1054
1055 /* printf( "%d %d\n", parent_h, parent_w ); */
1056
1057 if ( 1 ) {
1058 if ( TEST_AND(this->flags,GLUI_SUBWINDOW_TOP )) {
1059 main_panel->w = MAX( main_panel->w, parent_w );
1060 }
1061 else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
1062 main_panel->h = MAX( main_panel->h, parent_h );
1063 }
1064 else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) {
1065 main_panel->w = MAX( main_panel->w, parent_w );
1066 }
1067 else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
1068 main_panel->h = MAX( main_panel->h, parent_h );
1069 }
1070 }
1071 }
1072
1073 this->w = main_panel->w;
1074 this->h = main_panel->h;
1075 }
1076
1077
1078 /************************************ GLUI_Main::align_controls() **********/
1079
align_controls(GLUI_Control * control)1080 void GLUI_Main::align_controls( GLUI_Control *control )
1081 {
1082 GLUI_Control *child;
1083
1084 control->align();
1085
1086 child = (GLUI_Control*) control->first_child();
1087
1088 while( child != NULL ) {
1089 align_controls( child );
1090
1091 child = (GLUI_Control*)child->next();
1092 }
1093 }
1094
1095
1096
1097 /*********************************** GLUI::set_main_gfx_window() ************/
1098
set_main_gfx_window(int window_id)1099 void GLUI::set_main_gfx_window( int window_id )
1100 {
1101 main_gfx_window_id = window_id;
1102 }
1103
1104
1105 /********************************* GLUI_Main::post_update_main_gfx() ********/
1106
post_update_main_gfx(void)1107 void GLUI_Main::post_update_main_gfx( void )
1108 {
1109 int old_window;
1110
1111 if ( main_gfx_window_id > 0 ) {
1112 old_window = glutGetWindow();
1113 glutSetWindow( main_gfx_window_id );
1114 glutPostRedisplay();
1115 if( old_window > 0 )
1116 glutSetWindow( old_window );
1117 }
1118 }
1119
1120 /********************************* GLUI_Main::should_redraw_now() ********/
1121 /** Return true if this control should redraw itself immediately (front buffer);
1122 Or queue up a redraw and return false if it shouldn't (back buffer).
1123
1124 Called from GLUI_Control::redraw.
1125 */
should_redraw_now(GLUI_Control * ctl)1126 bool GLUI_Main::should_redraw_now(GLUI_Control *ctl)
1127 {
1128 switch (buffer_mode) {
1129 case buffer_front: return true; /* always draw in front-buffer mode */
1130 case buffer_back: {
1131 int orig = ctl->set_to_glut_window();
1132 glutPostRedisplay(); /* redraw soon */
1133 ctl->restore_window(orig);
1134 return false; /* don't draw now. */
1135 }
1136 }
1137 return false; /* never executed */
1138 }
1139
1140 /********************************* GLUI_Main::set_current_draw_buffer() ********/
1141
set_current_draw_buffer(void)1142 int GLUI_Main::set_current_draw_buffer( void )
1143 {
1144 /* Save old buffer */
1145 GLint state;
1146 glGetIntegerv( GL_DRAW_BUFFER, &state );
1147 /* Switch to new buffer */
1148 switch (buffer_mode) {
1149 case buffer_front: glDrawBuffer(GL_FRONT); break;
1150 case buffer_back: glDrawBuffer(GL_BACK); break; /* might not be needed... */
1151 }
1152 return (int)state;
1153 }
1154
1155
1156 /********************************* GLUI_Main::restore_draw_buffer() **********/
1157
restore_draw_buffer(int buffer_state)1158 void GLUI_Main::restore_draw_buffer( int buffer_state )
1159 {
1160 glDrawBuffer( buffer_state );
1161 }
1162
1163
1164 /******************************************** GLUI_Main::GLUI_Main() ********/
1165
GLUI_Main(void)1166 GLUI_Main::GLUI_Main( void )
1167 {
1168 mouse_button_down = false;
1169 w = 0;
1170 h = 0;
1171 active_control = NULL;
1172 mouse_over_control = NULL;
1173 main_gfx_window_id = -1;
1174 glut_window_id = -1;
1175 curr_modifiers = 0;
1176 closing = false;
1177 parent_window = -1;
1178 glui_id = GLUI_Master.glui_id_counter;
1179 GLUI_Master.glui_id_counter++;
1180
1181 font = GLUT_BITMAP_HELVETICA_12;
1182 curr_cursor = GLUT_CURSOR_LEFT_ARROW;
1183
1184 int r=200, g=200, b=200;
1185 bkgd_color.set( r,g,b );
1186 bkgd_color_f[0] = r / 255.0;
1187 bkgd_color_f[1] = g / 255.0;
1188 bkgd_color_f[2] = b / 255.0;
1189
1190 /*** Create the main panel ***/
1191 main_panel = new GLUI_Panel;
1192 main_panel->set_int_val( GLUI_PANEL_NONE );
1193 main_panel->glui = (GLUI*) this;
1194 main_panel->name = "\0";
1195 }
1196
1197 /************************************ GLUI_Main::draw_raised_box() **********/
1198
draw_raised_box(int x,int y,int w,int h)1199 void GLUI_Main::draw_raised_box( int x, int y, int w, int h )
1200 {
1201 w = w+x;
1202 h = h+y;
1203
1204 glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b );
1205 glBegin( GL_LINE_LOOP );
1206 glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 );
1207 glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
1208 glEnd();
1209
1210 glColor3d( 1.0, 1.0, 1.0 );
1211 glBegin( GL_LINE_STRIP );
1212 glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y );
1213 glEnd();
1214
1215 glColor3d( 0.0, 0.0, 0.0 );
1216 glBegin( GL_LINE_STRIP );
1217 glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h );
1218 glEnd();
1219
1220 glColor3d( .5, .5, .5 );
1221 glBegin( GL_LINE_STRIP );
1222 glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
1223 glEnd();
1224 }
1225
1226
1227 /************************************ GLUI_Main::draw_lowered_box() **********/
1228 /* Not quite perfect... **/
1229
draw_lowered_box(int x,int y,int w,int h)1230 void GLUI_Main::draw_lowered_box( int x, int y, int w, int h )
1231 {
1232 w = w+x;
1233 h = h+y;
1234
1235 glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b );
1236 glBegin( GL_LINE_LOOP );
1237 glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 );
1238 glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
1239 glEnd();
1240
1241 glColor3d( 0.0, 0.0, 0.0 );
1242 glBegin( GL_LINE_STRIP );
1243 glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y );
1244 glEnd();
1245
1246 glColor3d( 1.0, 1.0, 1.0 );
1247 glBegin( GL_LINE_STRIP );
1248 glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h );
1249 glEnd();
1250
1251 glColor3d( .5, .5, .5 );
1252 glBegin( GL_LINE_STRIP );
1253 glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
1254 glEnd();
1255 }
1256
1257
1258 /************************************* GLUI_Main::activate_control() *********/
1259
activate_control(GLUI_Control * control,int how)1260 void GLUI_Main::activate_control( GLUI_Control *control, int how )
1261 {
1262 /** Are we not activating a control in the same window as the
1263 previous active control? */
1264 if ( GLUI_Master.active_control_glui AND
1265 this != (GLUI_Main*) GLUI_Master.active_control_glui ) {
1266 GLUI_Master.active_control_glui->deactivate_current_control();
1267 }
1268
1269 /******* Now activate it *****/
1270 if ( control != NULL AND control->can_activate AND control->enabled ) {
1271 active_control = control;
1272
1273 control->activate(how);
1274
1275 /*if ( NOT active_control->is_container OR */
1276 /* active_control->type == GLUI_CONTROL_ROLLOUT) { */
1277 active_control->redraw();
1278 /*} */
1279 }
1280 else {
1281 active_control = NULL;
1282 }
1283
1284 /* printf( "activate: %d\n", glutGetWindow() ); */
1285 GLUI_Master.active_control = active_control;
1286 GLUI_Master.active_control_glui = (GLUI*) this;
1287 }
1288
1289
1290 /************************* GLUI_Main::deactivate_current_control() **********/
1291
deactivate_current_control(void)1292 void GLUI_Main::deactivate_current_control( void )
1293 {
1294 int orig;
1295
1296 if ( active_control != NULL ) {
1297 orig = active_control->set_to_glut_window();
1298
1299 active_control->deactivate();
1300
1301 /** If this isn't a container control, then redraw it in its
1302 deactivated state. Container controls, such as panels, look
1303 the same activated or not **/
1304
1305 /*if ( NOT active_control->is_container OR */
1306 /* active_control->type == GLUI_CONTROL_ROLLOUT ) { */
1307 active_control->redraw();
1308 /*} */
1309
1310 active_control->restore_window( orig );
1311
1312 active_control = NULL;
1313 }
1314
1315 /* printf( "deactivate: %d\n", glutGetWindow() ); */
1316 GLUI_Master.active_control = NULL;
1317 GLUI_Master.active_control_glui = NULL;
1318 }
1319
1320
1321 /****************************** GLUI_Main::find_next_control() **************/
1322
find_next_control_(GLUI_Control * control)1323 GLUI_Control *GLUI_Main::find_next_control_( GLUI_Control *control )
1324 {
1325 /*** THIS IS NOT find_next_control()! This is an unused older
1326 version (look at the underscore at the end) ***/
1327
1328 if ( control == NULL )
1329 return find_next_control_rec( main_panel );
1330 else
1331 return find_next_control_rec( control );
1332 }
1333
1334 /****************************** GLUI_Main::find_next_control() **************/
1335
find_next_control_rec(GLUI_Control * control)1336 GLUI_Control *GLUI_Main::find_next_control_rec( GLUI_Control *control )
1337 {
1338 GLUI_Control *child = NULL, *rec_control, *sibling;
1339
1340 /*** Recursively investigate children ***/
1341 child = (GLUI_Control*) control->first_child();
1342 if ( child ) {
1343 /*** If we can activate the first child, then do so ***/
1344 if ( child->can_activate AND child->enabled )
1345 return child;
1346 else /*** Recurse into first child ***/
1347 rec_control = find_next_control_rec( child );
1348
1349 if ( rec_control )
1350 return rec_control;
1351 }
1352
1353 /*** At this point, either we don't have children, or the child cannot
1354 be activated. So let's try the next sibling ***/
1355
1356 sibling = (GLUI_Control*) control->next();
1357 if ( sibling ) {
1358 if ( sibling->can_activate AND sibling->enabled )
1359 return sibling;
1360 else /*** Recurse into sibling ***/
1361 rec_control = find_next_control_rec( sibling );
1362
1363 if ( rec_control )
1364 return rec_control;
1365 }
1366
1367 return NULL;
1368 }
1369
1370
1371 /****************************** GLUI_Main::find_next_control() **************/
1372
find_next_control(GLUI_Control * control)1373 GLUI_Control *GLUI_Main::find_next_control( GLUI_Control *control )
1374 {
1375 GLUI_Control *tmp_control = NULL;
1376 int back_up;
1377
1378 if ( control == NULL )
1379 control = main_panel;
1380
1381 while( control != NULL ) {
1382 /** see if this control has a child **/
1383 tmp_control = (GLUI_Control*) control->first_child();
1384
1385 if ( tmp_control != NULL ) {
1386 if ( tmp_control->can_activate AND tmp_control->enabled )
1387 return tmp_control;
1388
1389 control = tmp_control; /* Descend into child */
1390 continue;
1391 }
1392
1393 /*** At this point, control has no children ***/
1394
1395 /** see if this control has a next sibling **/
1396 tmp_control = (GLUI_Control*) control->next();
1397
1398 if ( tmp_control != NULL ) {
1399 if ( tmp_control->can_activate AND tmp_control->enabled )
1400 return tmp_control;
1401
1402 control = tmp_control;
1403 continue;
1404 }
1405
1406 /** back up until we find a sibling of an ancestor **/
1407 back_up = true;
1408 while ( control->parent() AND back_up ) {
1409 control = (GLUI_Control*) control->parent();
1410
1411 if ( control->next() ) {
1412 control = (GLUI_Control*) control->next();
1413 if ( control->can_activate AND control->enabled )
1414 return control;
1415 else
1416 back_up = false;
1417
1418 /*** if ( control->is_container ) {
1419 tmp_control = control;
1420 control = NULL;
1421 break;
1422 }
1423 else {
1424 back_up = false;
1425 }
1426 ***/
1427 }
1428 }
1429
1430 /** Check if we've cycled back to the top... if so, return NULL **/
1431 if ( control == main_panel ) {
1432 return NULL;
1433 }
1434 }
1435 /*
1436 if ( tmp_control != NULL AND tmp_control->can_activate AND
1437 tmp_control->enabled ) {
1438 return tmp_control;
1439 }*/
1440
1441 return NULL;
1442 }
1443
1444
1445 /****************************** GLUI_Main::find_prev_control() **************/
1446
find_prev_control(GLUI_Control * control)1447 GLUI_Control *GLUI_Main::find_prev_control( GLUI_Control *control )
1448 {
1449 GLUI_Control *tmp_control, *next_control;
1450
1451 if ( control == NULL ) { /* here we find the last valid control */
1452 next_control = main_panel;
1453
1454 do {
1455 tmp_control = next_control;
1456 next_control = find_next_control( tmp_control );
1457 } while( next_control != NULL );
1458
1459 return tmp_control;
1460 }
1461 else { /* here we find the actual previous control */
1462 next_control = main_panel;
1463
1464 do {
1465 tmp_control = next_control;
1466 next_control = find_next_control( tmp_control );
1467 } while( next_control != NULL AND next_control != control );
1468
1469 if ( next_control == NULL OR tmp_control == main_panel )
1470 return NULL;
1471 else
1472 return tmp_control;
1473 }
1474 }
1475
1476 /************************* GLUI_Master_Object::set_glutIdleFunc() ***********/
1477
set_glutIdleFunc(void (* f)(void))1478 void GLUI_Master_Object::set_glutIdleFunc(void (*f)(void))
1479 {
1480 glut_idle_CB = f;
1481 GLUI_Master.glui_setIdleFuncIfNecessary();
1482 }
1483
1484
1485 /**************************************** GLUI::disable() ********************/
1486
disable(void)1487 void GLUI::disable( void )
1488 {
1489 deactivate_current_control();
1490 main_panel->disable();
1491 }
1492
1493
1494 /******************************************** GLUI::sync_live() **************/
1495
sync_live(void)1496 void GLUI::sync_live( void )
1497 {
1498 main_panel->sync_live(true, true);
1499 }
1500
1501
1502 /********************************* GLUI_Master_Object::sync_live_all() *****/
1503
sync_live_all(void)1504 void GLUI_Master_Object::sync_live_all( void )
1505 {
1506 GLUI *glui;
1507
1508 glui = (GLUI*) GLUI_Master.gluis.first_child();
1509 while( glui ) {
1510
1511 glui->sync_live(); /** sync it **/
1512
1513 glui = (GLUI*) glui->next();
1514 }
1515 }
1516
1517
1518 /************************************* GLUI_Master_Object::close() **********/
1519
close_all(void)1520 void GLUI_Master_Object::close_all( void )
1521 {
1522 GLUI *glui;
1523
1524 glui = (GLUI*) GLUI_Master.gluis.first_child();
1525 while( glui ) {
1526
1527 glui->close(); /** Set flag to close **/
1528
1529 glui = (GLUI*) glui->next();
1530 }
1531 }
1532
1533
1534 /************************************* GLUI_Main::close_internal() **********/
1535
close_internal(void)1536 void GLUI_Main::close_internal( void )
1537 {
1538 glutDestroyWindow(glutGetWindow()); /** Close this window **/
1539
1540 this->unlink();
1541
1542 if ( GLUI_Master.active_control_glui == this ) {
1543 GLUI_Master.active_control = NULL;
1544 GLUI_Master.active_control_glui = NULL;
1545 }
1546
1547 if ( parent_window != -1 ) {
1548 glutSetWindow( parent_window );
1549 int win_w = glutGet( GLUT_WINDOW_WIDTH );
1550 int win_h = glutGet( GLUT_WINDOW_HEIGHT );
1551 glutReshapeWindow(win_w+1, win_h);
1552 glutReshapeWindow(win_w-1, win_h);
1553 }
1554
1555 delete this->main_panel;
1556
1557 delete this;
1558 }
1559
1560
1561 /************************************************** GLUI::close() **********/
1562
close(void)1563 void GLUI::close( void )
1564 {
1565 int old_glut_window;
1566
1567 closing = true;
1568
1569 old_glut_window = glutGetWindow();
1570 glutSetWindow( get_glut_window_id() );
1571 glutPostRedisplay();
1572
1573 glutSetWindow( old_glut_window );
1574 }
1575
1576
1577 /************************** GLUI_Main::check_subwindow_position() **********/
1578
check_subwindow_position(void)1579 void GLUI_Main::check_subwindow_position( void )
1580 {
1581 /*** Reposition this window if subwindow ***/
1582 if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
1583
1584 int parent_w, parent_h, new_x, new_y;
1585 int old_window = glutGetWindow();
1586
1587 glutSetWindow( glut_window_id );
1588
1589 glutSetWindow( glutGet( GLUT_WINDOW_PARENT ));
1590 parent_w = glutGet( GLUT_WINDOW_WIDTH );
1591 parent_h = glutGet( GLUT_WINDOW_HEIGHT );
1592
1593 glutSetWindow( glut_window_id );
1594
1595 if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
1596 new_x = parent_w - this->w;
1597 new_y = 0;
1598 }
1599 else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
1600 new_x = 0;
1601 new_y = 0;
1602 }
1603 else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) {
1604 new_x = 0;
1605 new_y = parent_h - this->h;
1606 }
1607 else { /*** GLUI_SUBWINDOW_TOP ***/
1608 new_x = 0;
1609 new_y = 0;
1610 }
1611
1612 /** Now make adjustments based on presence of other subwindows **/
1613 GLUI *curr_glui;
1614 curr_glui = (GLUI*) GLUI_Master.gluis.first_child();
1615 while( curr_glui ) {
1616 if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND
1617 curr_glui->parent_window == this->parent_window ) {
1618
1619 if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) {
1620 }
1621 else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) {
1622 }
1623 else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) {
1624 }
1625 else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) AND
1626 ( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) OR
1627 TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) ) ) {
1628 /** If we are a RIGHT or LEFT subwindow, and there exists some
1629 TOP subwindow, bump our position down **/
1630
1631 new_y += curr_glui->h;
1632 }
1633
1634 /** CHeck multiple subwins at same position **/
1635 /** We check the glui_id's: only the glui with the higher
1636 ID number (meaning it was created later) gets bumped over **/
1637 if ( curr_glui != this AND this->glui_id > curr_glui->glui_id ) {
1638 if ( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) AND
1639 TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) {
1640 new_x += curr_glui->w;
1641 }
1642 else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_TOP ) AND
1643 TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) {
1644 new_y += curr_glui->h;
1645 }
1646 else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_BOTTOM ) AND
1647 TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) {
1648 new_y -= curr_glui->h;
1649 }
1650 else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) AND
1651 TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) {
1652 new_x -= curr_glui->w;
1653 }
1654
1655 }
1656 }
1657
1658 curr_glui = (GLUI*) curr_glui->next();
1659 }
1660
1661
1662
1663 CLAMP( new_x, 0, new_x );
1664 CLAMP( new_y, 0, new_y );
1665
1666 glutPositionWindow( new_x, new_y );
1667 /* glutPostRedisplay(); */
1668
1669 glutSetWindow( old_window );
1670 }
1671 }
1672
1673
1674 /********************************* GLUI_Master_Object::reshape() **********/
1675 /* This gets called by the user from a GLUT reshape callback. So we look */
1676 /* for subwindows that belong to the current window */
1677
reshape(void)1678 void GLUI_Master_Object::reshape( void )
1679 {
1680 GLUI *glui;
1681 int current_window;
1682
1683 current_window = glutGetWindow();
1684
1685 glui = (GLUI*) GLUI_Master.gluis.first_child();
1686 while( glui ) {
1687 if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
1688 glui->parent_window == current_window ) {
1689 glutSetWindow( glui->get_glut_window_id());
1690 glui->check_subwindow_position();
1691 }
1692
1693 glui = (GLUI*) glui->next();
1694 }
1695
1696 glutSetWindow(current_window);
1697 }
1698
1699
1700 /**************************** GLUI_Master_Object::set_glutReshapeFunc() *****/
1701
set_glutReshapeFunc(void (* f)(int width,int height))1702 void GLUI_Master_Object::set_glutReshapeFunc(void (*f)(int width, int height))
1703 {
1704 glutReshapeFunc( glui_reshape_func );
1705 add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_RESHAPE, (void*) f);
1706 }
1707
1708
1709 /**************************** GLUI_Master_Object::set_glutKeyboardFunc() ****/
1710
set_glutKeyboardFunc(void (* f)(unsigned char key,int x,int y))1711 void GLUI_Master_Object::set_glutKeyboardFunc(void (*f)(unsigned char key,
1712 int x, int y))
1713 {
1714 glutKeyboardFunc( glui_keyboard_func );
1715 add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_KEYBOARD, (void*) f);
1716 }
1717
1718
1719 /*********************** GLUI_Master_Object::set_glutSpecialFunc() **********/
1720
1721
1722
set_glutSpecialUpFunc(void (* f)(int key,int x,int y))1723 void GLUI_Master_Object::set_glutSpecialUpFunc(void (*f)(int key,
1724 int x, int y))
1725 {
1726 glutSpecialUpFunc( glui_special_up_func );
1727 add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL_UP, (void*) f);
1728 }
1729
1730
set_glutSpecialFunc(void (* f)(int key,int x,int y))1731 void GLUI_Master_Object::set_glutSpecialFunc(void (*f)(int key,
1732 int x, int y))
1733 {
1734 glutSpecialFunc( glui_special_func );
1735 add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL, (void*) f);
1736 }
1737
1738
1739 /*********************** GLUI_Master_Object::set_glutMouseFunc() **********/
1740
set_glutMouseFunc(void (* f)(int button,int state,int x,int y))1741 void GLUI_Master_Object::set_glutMouseFunc(void (*f)(int button, int state,
1742 int x, int y))
1743 {
1744 glutMouseFunc( glui_mouse_func );
1745 add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_MOUSE, (void*) f);
1746 }
1747
1748
1749 /****************************** glui_parent_window_reshape_func() **********/
1750 /* This is the reshape callback for a window that contains subwindows */
1751
glui_parent_window_reshape_func(int w,int h)1752 void glui_parent_window_reshape_func( int w, int h )
1753 {
1754 int current_window;
1755 GLUI *glui;
1756 int first = true;
1757
1758 /* printf( "glui_parent_window_reshape_func: %d\n", glutGetWindow() ); */
1759
1760 current_window = glutGetWindow();
1761
1762 glui = (GLUI*) GLUI_Master.gluis.first_child();
1763 while( glui ) {
1764 if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
1765 glui->parent_window == current_window ) {
1766 glutSetWindow( glui->get_glut_window_id());
1767 glui->check_subwindow_position();
1768 glutSetWindow( current_window );
1769
1770 if ( first ) {
1771 if (glui->glut_reshape_CB) glui->glut_reshape_CB( w, h );
1772
1773 first = false;
1774 }
1775 }
1776
1777 glui = (GLUI*) glui->next();
1778 }
1779 }
1780
1781
1782 /****************************** glui_parent_window_keyboard_func() **********/
1783
glui_parent_window_keyboard_func(unsigned char key,int x,int y)1784 void glui_parent_window_keyboard_func(unsigned char key, int x, int y)
1785 {
1786 /* printf( "glui_parent_window_keyboard_func: %d\n", glutGetWindow() ); */
1787
1788 int current_window;
1789 GLUI *glui;
1790
1791 current_window = glutGetWindow();
1792
1793 if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) {
1794 glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
1795
1796 GLUI_Master.active_control_glui->keyboard(key,x,y);
1797
1798 glutSetWindow( current_window );
1799 }
1800 else {
1801 glui = (GLUI*) GLUI_Master.gluis.first_child();
1802 while( glui ) {
1803 if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
1804 glui->parent_window == current_window AND
1805 glui->glut_keyboard_CB )
1806 {
1807 glui->glut_keyboard_CB( key, x, y );
1808 break;
1809 }
1810
1811 glui = (GLUI*) glui->next();
1812 }
1813 }
1814 }
1815
1816
1817 /****************************** glui_parent_window_special_func() **********/
1818
glui_parent_window_special_func(int key,int x,int y)1819 void glui_parent_window_special_func(int key, int x, int y)
1820 {
1821 /*printf( "glui_parent_window_special_func: %d\n", glutGetWindow() ); */
1822
1823 int current_window;
1824 GLUI *glui;
1825
1826 /** If clicking in the main area of a window w/subwindows,
1827 deactivate any current control **/
1828 if ( GLUI_Master.active_control_glui != NULL )
1829 GLUI_Master.active_control_glui->deactivate_current_control();
1830
1831 /*** Now pass on the mouse event ***/
1832
1833 current_window = glutGetWindow();
1834
1835 glui = (GLUI*) GLUI_Master.gluis.first_child();
1836 while( glui ) {
1837 if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
1838 glui->parent_window == current_window )
1839 {
1840 glutSetWindow( glui->get_glut_window_id());
1841 if (glui->glut_special_CB) glui->glut_special_CB( key, x, y );
1842 break;
1843 }
1844
1845 glui = (GLUI*) glui->next();
1846 }
1847 }
1848
1849
1850 /****************************** glui_parent_window_mouse_func() **********/
1851
glui_parent_window_mouse_func(int button,int state,int x,int y)1852 void glui_parent_window_mouse_func(int button, int state, int x, int y)
1853 {
1854 int current_window;
1855 GLUI *glui;
1856
1857 /** If clicking in the main area of a window w/subwindows,
1858 deactivate any current control **/
1859 if ( GLUI_Master.active_control_glui != NULL )
1860 GLUI_Master.active_control_glui->deactivate_current_control();
1861
1862
1863 /*** Now pass on the mouse event ***/
1864
1865 current_window = glutGetWindow();
1866
1867 glui = (GLUI*) GLUI_Master.gluis.first_child();
1868 while( glui ) {
1869 if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
1870 glui->parent_window == current_window AND
1871 glui->glut_mouse_CB)
1872 {
1873 glutSetWindow( glui->get_glut_window_id());
1874 glui->glut_mouse_CB( button, state, x, y );
1875 break;
1876 }
1877
1878 glui = (GLUI*) glui->next();
1879 }
1880 }
1881
1882
1883 /************************** GLUI_Master_Object::find_glut_window() **********/
1884
find_glut_window(int window_id)1885 GLUI_Glut_Window *GLUI_Master_Object::find_glut_window( int window_id )
1886 {
1887 GLUI_Glut_Window *window;
1888
1889 window = (GLUI_Glut_Window*) glut_windows.first_child();
1890 while( window ) {
1891 if ( window->glut_window_id == window_id )
1892 return window;
1893
1894 window = (GLUI_Glut_Window*) window->next();
1895 }
1896
1897 /*** Window not found - return NULL ***/
1898 return NULL;
1899 }
1900
1901
1902 /******************** GLUI_Master_Object::add_cb_to_glut_window() **********/
1903
add_cb_to_glut_window(int window_id,int cb_type,void * cb)1904 void GLUI_Master_Object::add_cb_to_glut_window(int window_id,
1905 int cb_type,void *cb)
1906 {
1907 GLUI_Glut_Window *window;
1908
1909 window = find_glut_window( window_id );
1910 if ( NOT window ) {
1911 /*** Allocate new window structure ***/
1912
1913 window = new GLUI_Glut_Window;
1914 window->glut_window_id = window_id;
1915 window->link_this_to_parent_last( (GLUI_Node*) &this->glut_windows );
1916 }
1917
1918 switch( cb_type ) {
1919 case GLUI_GLUT_RESHAPE:
1920 window->glut_reshape_CB = (void(*)(int,int)) cb;
1921 break;
1922 case GLUI_GLUT_DISPLAY:
1923 window->glut_display_CB = (void(*)()) cb;
1924 break;
1925 case GLUI_GLUT_KEYBOARD:
1926 window->glut_keyboard_CB = (void(*)(unsigned char,int,int)) cb;
1927 break;
1928 case GLUI_GLUT_SPECIAL:
1929 window->glut_special_CB = (void(*)(int,int,int)) cb;
1930 break;
1931 case GLUI_GLUT_SPECIAL_UP:
1932 window->glut_special_up_CB = (void(*)(int,int,int)) cb;
1933 break;
1934 case GLUI_GLUT_MOUSE:
1935 window->glut_mouse_CB = (void(*)(int,int,int,int)) cb;
1936 break;
1937 case GLUI_GLUT_MOTION:
1938 window->glut_motion_CB = (void(*)(int,int)) cb;
1939 break;
1940 case GLUI_GLUT_PASSIVE_MOTION:
1941 window->glut_passive_motion_CB = (void(*)(int,int)) cb;
1942 break;
1943 case GLUI_GLUT_ENTRY:
1944 window->glut_entry_CB = (void(*)(int)) cb;
1945 break;
1946 case GLUI_GLUT_VISIBILITY:
1947 window->glut_visibility_CB= (void(*)(int)) cb;
1948 break;
1949 }
1950 }
1951
1952
1953 /************* GLUI_Master_Object::set_left_button_glut_menu_control() *****/
1954
set_left_button_glut_menu_control(GLUI_Control * control)1955 void GLUI_Master_Object::set_left_button_glut_menu_control(
1956 GLUI_Control *control )
1957 {
1958 curr_left_button_glut_menu = control;
1959 }
1960
1961
1962 /******************************* GLUI_Main::set_ortho_projection() **********/
1963
set_ortho_projection(void)1964 void GLUI_Main::set_ortho_projection( void )
1965 {
1966 int win_h, win_w;
1967
1968 win_w = glutGet( GLUT_WINDOW_WIDTH );
1969 win_h = glutGet( GLUT_WINDOW_HEIGHT );
1970
1971 glMatrixMode( GL_PROJECTION );
1972 glLoadIdentity();
1973 /* gluOrtho2D( 0.0, (float) win_w, 0.0, (float) win_h ); */
1974 glOrtho( 0.0, (float)win_w, 0.0, (float) win_h, -1000.0, 1000.0 );
1975
1976 glMatrixMode( GL_MODELVIEW );
1977
1978 return; /****-----------------------------------------------***/
1979
1980 glMatrixMode( GL_MODELVIEW );
1981 glLoadIdentity();
1982
1983 /*** Rotate image so y increases upwards, contrary to OpenGL axes ***/
1984 glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 );
1985 glRotatef( 180.0, 0.0, 1.0, 0.0 );
1986 glRotatef( 180.0, 0.0, 0.0, 1.0 );
1987 glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 );
1988 }
1989
1990
1991 /******************************* GLUI_Main::set_viewport() **********/
1992
set_viewport(void)1993 void GLUI_Main::set_viewport( void )
1994 {
1995 glViewport( 0, 0, main_panel->w, main_panel->h );
1996 }
1997
1998
1999 /****************************** GLUI_Main::refresh() ****************/
2000
refresh(void)2001 void GLUI_Main::refresh( void )
2002 {
2003 int orig;
2004
2005 /****** GLUI_Glut_Window *glut_window;
2006 int current_window;
2007 current_window = glutGetWindow();
2008 glut_window = GLUI_Master.find_glut_window( current_window );
2009 if ( glut_window ) {
2010 glut_window->glut_reshape_CB(w,h);
2011 ******/
2012
2013 orig = glutGetWindow();
2014
2015 pack_controls();
2016
2017 if ( glut_window_id > 0 )
2018 glutSetWindow( glut_window_id );
2019
2020
2021 if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
2022 /*** GLUI subwindow ***/
2023
2024 check_subwindow_position();
2025 }
2026 else {
2027 /*** Standalone GLUI window ***/
2028
2029 glutReshapeWindow( this->h, this->w );
2030
2031 }
2032
2033 glutPostRedisplay();
2034 glutSetWindow( orig);
2035 }
2036
2037
2038
2039 /***************** GLUI_Master_Object::get_main_gfx_viewport() ***********/
2040
get_viewport_area(int * x,int * y,int * w,int * h)2041 void GLUI_Master_Object::get_viewport_area( int *x, int *y,
2042 int *w, int *h )
2043 {
2044 GLUI *curr_glui;
2045 int curr_x, curr_y, curr_w, curr_h;
2046 int curr_window;
2047
2048 curr_window = glutGetWindow();
2049 curr_x = 0;
2050 curr_y = 0;
2051 curr_w = glutGet( GLUT_WINDOW_WIDTH );
2052 curr_h = glutGet( GLUT_WINDOW_HEIGHT );
2053
2054 curr_glui = (GLUI*) gluis.first_child();
2055 while( curr_glui ) {
2056 if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND
2057 curr_glui->parent_window == curr_window ) {
2058
2059 /* printf( "%s -> %d %d %d\n", curr_glui->window_name.c_str(), curr_glui->flags,
2060 curr_glui->w, curr_glui->h );*/
2061
2062 if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) {
2063 curr_x += curr_glui->w;
2064 curr_w -= curr_glui->w;
2065 }
2066 else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) {
2067 curr_y += curr_glui->h;
2068 curr_h -= curr_glui->h;
2069 }
2070 else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) {
2071 curr_w -= curr_glui->w;
2072 }
2073 else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) {
2074 curr_h -= curr_glui->h;
2075 }
2076 }
2077
2078 curr_glui = (GLUI*) curr_glui->next();
2079 }
2080
2081 curr_x = MAX( 0, curr_x );
2082 curr_y = MAX( 0, curr_y );
2083 curr_w = MAX( 0, curr_w );
2084 curr_h = MAX( 0, curr_h );
2085
2086 *x = curr_x;
2087 *y = curr_y;
2088 *w = curr_w;
2089 *h = curr_h;
2090 }
2091
2092
2093 /*****************GLUI_Master_Object::auto_set_main_gfx_viewport() **********/
2094
auto_set_viewport(void)2095 void GLUI_Master_Object::auto_set_viewport( void )
2096 {
2097 int x, y, w, h;
2098
2099 get_viewport_area( &x, &y, &w, &h );
2100 glViewport( MAX(x,0), MAX(y,0), MAX(w,0), MAX(h,0) );
2101 }
2102
2103
2104
2105 /***************************************** GLUI::show() **********************/
2106
show(void)2107 void GLUI::show( void )
2108 {
2109 int orig_window;
2110
2111 orig_window = main_panel->set_to_glut_window();
2112
2113 glutShowWindow();
2114
2115 main_panel->restore_window(orig_window);
2116 }
2117
2118
2119
2120 /***************************************** GLUI::hide() **********************/
2121
hide(void)2122 void GLUI::hide( void )
2123 {
2124 int orig_window;
2125
2126 this->deactivate_current_control();
2127
2128 orig_window = main_panel->set_to_glut_window();
2129
2130 glutHideWindow();
2131
2132 main_panel->restore_window(orig_window);
2133 }
2134
2135
2136 /**************** GLUI_DrawingSentinal **************/
GLUI_DrawingSentinal(GLUI_Control * c_)2137 GLUI_DrawingSentinal::GLUI_DrawingSentinal(GLUI_Control *c_)
2138 :c(c_)
2139 {
2140 orig_win = c->set_to_glut_window();
2141 orig_buf = c->glui->set_current_draw_buffer();
2142 }
~GLUI_DrawingSentinal()2143 GLUI_DrawingSentinal::~GLUI_DrawingSentinal() {
2144 c->glui->restore_draw_buffer(orig_buf);
2145 c->restore_window(orig_win);
2146 }
2147
2148
glui_setIdleFuncIfNecessary(void)2149 void GLUI_Master_Object::glui_setIdleFuncIfNecessary( void )
2150 {
2151 GLUI *glui;
2152
2153 glui = (GLUI*) GLUI_Master.gluis.first_child();
2154 int necessary;
2155 if (this->glut_idle_CB)
2156 necessary = true;
2157 else {
2158 necessary = false;
2159 while( glui ) {
2160 if( glui->needs_idle() ) {
2161 necessary = true;
2162 break;
2163 }
2164 glui = (GLUI*) glui->next();
2165 }
2166 }
2167 if( necessary )
2168 glutIdleFunc( glui_idle_func );
2169 else
2170 glutIdleFunc( NULL );
2171 }
2172