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