| /**************************************************************************** |
| |
| GLUI User Interface Toolkit (LGPL) |
| --------------------------- |
| |
| glui.cpp |
| |
| -------------------------------------------------- |
| |
| Copyright (c) 1998 Paul Rademacher |
| |
| WWW: http://sourceforge.net/projects/glui/ |
| Forums: http://sourceforge.net/forum/?group_id=92496 |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| This library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with this library; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| |
| *****************************************************************************/ |
| #include "glui_internal_control.h" |
| |
| |
| /** |
| Note: moving this routine here from glui_add_controls.cpp prevents the linker |
| from touching glui_add_controls.o in non-deprecated programs, which |
| descreases the linked size of small GLUI programs substantially (100K+). (OSL 2006/06) |
| */ |
| void GLUI_Node::add_child_to_control(GLUI_Node *parent,GLUI_Control *child) |
| { |
| GLUI_Control *parent_control; |
| |
| /*** Collapsible nodes have to be handled differently, b/c the first and |
| last children are swapped in and out ***/ |
| parent_control = ((GLUI_Control*)parent); |
| if ( parent_control->collapsible == true ) { |
| if ( NOT parent_control->is_open ) { |
| /** Swap in the original first and last children **/ |
| parent_control->child_head = parent_control->collapsed_node.child_head; |
| parent_control->child_tail = parent_control->collapsed_node.child_tail; |
| |
| /*** Link this control ***/ |
| child->link_this_to_parent_last( parent_control ); |
| |
| /** Swap the children back out ***/ |
| parent_control->collapsed_node.child_head = parent_control->child_head; |
| parent_control->collapsed_node.child_tail = parent_control->child_tail; |
| parent_control->child_head = NULL; |
| parent_control->child_tail = NULL; |
| } |
| else { |
| child->link_this_to_parent_last( parent_control ); |
| } |
| } |
| else { |
| child->link_this_to_parent_last( parent_control ); |
| } |
| child->glui = (GLUI*) parent_control->glui; |
| child->update_size(); |
| child->enabled = parent_control->enabled; |
| child->glui->refresh(); |
| |
| /** Now set the 'hidden' var based on the parent **/ |
| if ( parent_control->hidden OR |
| (parent_control->collapsible AND NOT parent_control->is_open ) ) |
| { |
| child->hidden = true; |
| } |
| } |
| |
| |
| /************************************ GLUI_Node::add_control() **************/ |
| |
| int GLUI_Node::add_control( GLUI_Control *child ) |
| { |
| add_child_to_control(this,child); |
| return true; |
| } |
| |
| /************************************ GLUI_Main::add_control() **************/ |
| |
| int GLUI_Main::add_control( GLUI_Node *parent, GLUI_Control *control ) |
| { |
| add_child_to_control(parent,control); |
| return true; |
| } |
| |
| |
| |
| /*** This object must be used to create a GLUI ***/ |
| |
| GLUI_Master_Object GLUI_Master; |
| |
| /************************************ finish_drawing() *********** |
| Probably a silly routine. Called after all event handling callbacks. |
| */ |
| |
| static void finish_drawing(void) |
| { |
| glFinish(); |
| } |
| |
| /************************************ GLUI_CB::operator()() ************/ |
| void GLUI_CB::operator()(GLUI_Control*ctrl) const |
| { |
| if (idCB) idCB(ctrl->user_id); |
| if (objCB) objCB(ctrl); |
| } |
| |
| |
| /************************************************ GLUI::GLUI() **********/ |
| |
| int GLUI::init( const char *text, long flags, int x, int y, int parent_window ) |
| { |
| int old_glut_window; |
| |
| this->flags = flags; |
| |
| window_name = text; |
| |
| buffer_mode = buffer_back; ///< New smooth way |
| //buffer_mode = buffer_front; ///< Old flickery way (a bit faster). |
| |
| /*** We copy over the current window callthroughs ***/ |
| /*** (I think this might actually only be needed for subwindows) ***/ |
| /* glut_keyboard_CB = GLUI_Master.glut_keyboard_CB; |
| glut_reshape_CB = GLUI_Master.glut_reshape_CB; |
| glut_special_CB = GLUI_Master.glut_special_CB; |
| glut_mouse_CB = GLUI_Master.glut_mouse_CB;*/ |
| |
| |
| if ( (flags & GLUI_SUBWINDOW) != GLUI_SUBWINDOW ) { /* not a subwindow, creating a new top-level window */ |
| old_glut_window = glutGetWindow(); |
| |
| create_standalone_window( window_name.c_str(), x, y ); |
| setup_default_glut_callbacks(); |
| |
| if ( old_glut_window > 0 ) |
| glutSetWindow( old_glut_window ); |
| |
| top_level_glut_window_id = glut_window_id; |
| } |
| else /* *is* a subwindow */ |
| { |
| old_glut_window = glutGetWindow(); |
| |
| create_subwindow( parent_window, flags ); |
| setup_default_glut_callbacks(); |
| |
| if ( old_glut_window > 0 ) |
| glutSetWindow( old_glut_window ); |
| |
| top_level_glut_window_id = parent_window; |
| |
| /* |
| glutReshapeFunc( glui_parent_window_reshape_func ); |
| glutSpecialFunc( glui_parent_window_special_func ); |
| glutKeyboardFunc( glui_parent_window_keyboard_func ); |
| glutMouseFunc( glui_parent_window_mouse_func ); |
| */ |
| |
| } |
| |
| return true; |
| } |
| |
| |
| /**************************** GLUI_Main::create_standalone_window() ********/ |
| |
| void GLUI_Main::create_standalone_window( const char *name, int x, int y ) |
| { |
| glutInitWindowSize( 100, 100 ); |
| if ( x >= 0 OR y >= 0 ) |
| glutInitWindowPosition( x, y ); |
| glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); |
| glut_window_id = glutCreateWindow( name ); |
| } |
| |
| |
| /******************************** GLUI_Main::create_subwindow() **********/ |
| |
| void GLUI_Main::create_subwindow( int parent_window, int window_alignment ) |
| { |
| glut_window_id = glutCreateSubWindow(parent_window, 0,0, 100, 100); |
| this->parent_window = parent_window; |
| } |
| |
| |
| /**************************** GLUI_Main::setup_default_glut_callbacks() *****/ |
| |
| void GLUI_Main::setup_default_glut_callbacks( void ) |
| { |
| glutDisplayFunc( glui_display_func ); |
| glutReshapeFunc( glui_reshape_func ); |
| glutKeyboardFunc( glui_keyboard_func ); |
| glutSpecialFunc( glui_special_func ); |
| glutMouseFunc( glui_mouse_func ); |
| glutMotionFunc( glui_motion_func ); |
| glutPassiveMotionFunc( glui_passive_motion_func ); |
| glutEntryFunc( glui_entry_func ); |
| glutVisibilityFunc( glui_visibility_func ); |
| /* glutIdleFunc( glui_idle_func ); // FIXME! 100% CPU usage! */ |
| } |
| |
| |
| /********************************************** glui_display_func() ********/ |
| |
| void glui_display_func(void) |
| { |
| GLUI *glui; |
| |
| /* printf( "display func\n" ); */ |
| |
| glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); |
| |
| if ( glui ) { |
| glui->display(); |
| /* |
| Do not do anything after the above line, b/c the GLUI |
| window might have just closed itself |
| */ |
| } |
| } |
| |
| |
| /********************************************** glui_reshape_func() ********/ |
| |
| void glui_reshape_func(int w,int h ) |
| { |
| GLUI *glui; |
| GLUI_Glut_Window *glut_window; |
| int current_window; |
| |
| /*printf( "glui_reshape_func(): %d w/h: %d/%d\n", glutGetWindow(), w, h ); */ |
| |
| current_window = glutGetWindow(); |
| |
| /*** First check if this is main glut window ***/ |
| glut_window = GLUI_Master.find_glut_window( current_window ); |
| if ( glut_window ) { |
| if (glut_window->glut_reshape_CB) glut_window->glut_reshape_CB(w,h); |
| |
| /*** Now send reshape events to all subwindows ***/ |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while(glui) { |
| if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND |
| glui->parent_window == current_window ) { |
| glutSetWindow( glui->get_glut_window_id()); |
| glui->reshape(w,h); |
| /* glui->check_subwindow_position(); */ |
| } |
| glui = (GLUI*) glui->next(); |
| } |
| } |
| else { |
| /*** A standalone GLUI window ***/ |
| |
| glui = GLUI_Master.find_glui_by_window_id( current_window ); |
| |
| if ( glui ) { |
| glui->reshape(w,h); |
| } |
| } |
| } |
| |
| /********************************************** glui_keyboard_func() ********/ |
| |
| void glui_keyboard_func(unsigned char key, int x, int y) |
| { |
| GLUI *glui; |
| int current_window; |
| GLUI_Glut_Window *glut_window; |
| |
| current_window = glutGetWindow(); |
| glut_window = GLUI_Master.find_glut_window( current_window ); |
| |
| /*printf( "key: %d\n", current_window ); */ |
| |
| if ( glut_window ) { /** Was event in a GLUT window? **/ |
| if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) { |
| glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() ); |
| |
| GLUI_Master.active_control_glui->keyboard(key,x,y); |
| finish_drawing(); |
| |
| glutSetWindow( current_window ); |
| } |
| else { |
| if (glut_window->glut_keyboard_CB) |
| glut_window->glut_keyboard_CB( key, x, y ); |
| } |
| } |
| else { /*** Nope, event was in a standalone GLUI window **/ |
| glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); |
| |
| if ( glui ) { |
| glui->keyboard(key,x,y); |
| finish_drawing(); |
| } |
| } |
| } |
| |
| |
| |
| |
| void glui_special_up_func(int key, int x, int y) |
| { |
| GLUI *glui; |
| int current_window; |
| GLUI_Glut_Window *glut_window; |
| |
| current_window = glutGetWindow(); |
| glut_window = GLUI_Master.find_glut_window( current_window ); |
| |
| if (glut_window) /** Was event in a GLUT window? **/ |
| { |
| if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) |
| { |
| glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() ); |
| |
| GLUI_Master.active_control_glui->special_up(key,x,y); |
| finish_drawing(); |
| |
| glutSetWindow( current_window ); |
| } |
| else |
| { |
| if (glut_window->glut_special_up_CB) |
| glut_window->glut_special_up_CB( key, x, y ); |
| } |
| } |
| else /*** Nope, event was in a standalone GLUI window **/ |
| { |
| glui = GLUI_Master.find_glui_by_window_id(glutGetWindow()); |
| |
| if ( glui ) |
| { |
| glui->special_up(key,x,y); |
| finish_drawing(); |
| } |
| } |
| } |
| |
| |
| |
| /************************************************ glui_special_func() ********/ |
| |
| void glui_special_func(int key, int x, int y) |
| { |
| GLUI *glui; |
| int current_window; |
| GLUI_Glut_Window *glut_window; |
| |
| current_window = glutGetWindow(); |
| glut_window = GLUI_Master.find_glut_window( current_window ); |
| |
| if (glut_window) /** Was event in a GLUT window? **/ |
| { |
| if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) |
| { |
| glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() ); |
| |
| GLUI_Master.active_control_glui->special(key,x,y); |
| finish_drawing(); |
| |
| glutSetWindow( current_window ); |
| } |
| else |
| { |
| if (glut_window->glut_special_CB) |
| glut_window->glut_special_CB( key, x, y ); |
| } |
| } |
| else /*** Nope, event was in a standalone GLUI window **/ |
| { |
| glui = GLUI_Master.find_glui_by_window_id(glutGetWindow()); |
| |
| if ( glui ) |
| { |
| glui->special(key,x,y); |
| finish_drawing(); |
| } |
| } |
| } |
| |
| /********************************************** glui_mouse_func() ********/ |
| |
| void glui_mouse_func(int button, int state, int x, int y) |
| { |
| GLUI *glui; |
| int current_window; |
| GLUI_Glut_Window *glut_window; |
| |
| current_window = glutGetWindow(); |
| glut_window = GLUI_Master.find_glut_window( current_window ); |
| |
| if ( glut_window ) { /** Was event in a GLUT window? **/ |
| if ( GLUI_Master.active_control_glui != NULL ) |
| GLUI_Master.active_control_glui->deactivate_current_control(); |
| |
| if (glut_window->glut_mouse_CB) |
| glut_window->glut_mouse_CB( button, state, x, y ); |
| finish_drawing(); |
| } |
| else { /** Nope - event was in a GLUI standalone window **/ |
| glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); |
| if ( glui ) { |
| glui->passive_motion( 0,0 ); |
| glui->mouse( button, state, x, y ); |
| finish_drawing(); |
| } |
| } |
| } |
| |
| |
| /********************************************** glui_motion_func() ********/ |
| |
| void glui_motion_func(int x, int y) |
| { |
| GLUI *glui; |
| |
| glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); |
| |
| if ( glui ) { |
| glui->motion(x,y); |
| finish_drawing(); |
| } |
| |
| } |
| |
| |
| /**************************************** glui_passive_motion_func() ********/ |
| |
| void glui_passive_motion_func(int x, int y) |
| { |
| GLUI *glui; |
| |
| glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); |
| |
| if ( glui ) { |
| glui->passive_motion(x,y); |
| finish_drawing(); |
| } |
| } |
| |
| |
| /********************************************** glui_entry_func() ********/ |
| |
| void glui_entry_func(int state) |
| { |
| GLUI *glui; |
| |
| glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); |
| |
| if ( glui ) { |
| glui->entry(state); |
| } |
| } |
| |
| |
| /******************************************** glui_visibility_func() ********/ |
| |
| void glui_visibility_func(int state) |
| { |
| GLUI *glui; |
| |
| /* printf( "IN GLUI VISIBILITY()\n" ); */ |
| /* fflush( stdout ); */ |
| |
| glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() ); |
| |
| if ( glui ) { |
| glui->visibility(state); |
| } |
| } |
| |
| |
| /********************************************** glui_idle_func() ********/ |
| /* Send idle event to each glui, then to the main window */ |
| |
| void glui_idle_func(void) |
| { |
| GLUI *glui; |
| |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while( glui ) { |
| glui->idle(); |
| finish_drawing(); |
| |
| glui = (GLUI*) glui->next(); |
| } |
| |
| if ( GLUI_Master.glut_idle_CB ) { |
| /*** We set the current glut window before calling the user's |
| idle function, even though glut explicitly says the window id is |
| undefined in an idle callback. ***/ |
| |
| /** Check what the current window is first ***/ |
| |
| /*** Arbitrarily set the window id to the main gfx window of the |
| first glui window ***/ |
| /* int current_window, new_window; */ |
| /* current_window = glutGetWindow(); */ |
| /* if (GLUI_Master.gluis.first_child() != NULL ) { */ |
| /* new_window = ((GLUI_Main*)GLUI_Master.gluis.first_child())-> */ |
| /* main_gfx_window_id; */ |
| /* if ( new_window > 0 AND new_window != old_window ) { */ |
| /* --- Window is changed only if its not already the current window ---*/ |
| /* glutSetWindow( new_window ); */ |
| /* } */ |
| /*} */ |
| |
| GLUI_Master.glut_idle_CB(); |
| } |
| } |
| |
| /*********************************** GLUI_Master_Object::GLUI_Master_Object() ******/ |
| |
| GLUI_Master_Object::GLUI_Master_Object() |
| : glui_id_counter(1), |
| glut_idle_CB(NULL) |
| { |
| } |
| |
| GLUI_Master_Object::~GLUI_Master_Object() |
| { |
| } |
| |
| /*********************************** GLUI_Master_Object::create_glui() ******/ |
| |
| GLUI *GLUI_Master_Object::create_glui( const char *name, long flags,int x,int y ) |
| { |
| GLUI *new_glui = new GLUI; |
| new_glui->init( name, flags, x, y, -1 ); |
| new_glui->link_this_to_parent_last( &this->gluis ); |
| return new_glui; |
| } |
| |
| |
| /************************** GLUI_Master_Object::create_glui_subwindow() ******/ |
| |
| GLUI *GLUI_Master_Object::create_glui_subwindow( int parent_window, |
| long flags ) |
| { |
| GLUI *new_glui = new GLUI; |
| GLUI_String new_name; |
| glui_format_str( new_name, "subwin_%p", this ); |
| |
| new_glui->init( new_name.c_str(), flags | GLUI_SUBWINDOW, 0,0, |
| parent_window ); |
| new_glui->main_panel->set_int_val( GLUI_PANEL_EMBOSSED ); |
| new_glui->link_this_to_parent_last( &this->gluis ); |
| return new_glui; |
| } |
| |
| |
| /********************** GLUI_Master_Object::find_glui_by_window_id() ********/ |
| |
| GLUI *GLUI_Master_Object::find_glui_by_window_id( int window_id ) |
| { |
| GLUI_Node *node; |
| |
| node = gluis.first_child(); |
| while( node ) { |
| if ( ((GLUI*)node)->get_glut_window_id() == window_id ) |
| return (GLUI*) node; |
| |
| node = node->next(); |
| } |
| return NULL; |
| } |
| |
| |
| /******************************************** GLUI_Main::display() **********/ |
| |
| void GLUI_Main::display( void ) |
| { |
| int win_w, win_h; |
| |
| /* SUBTLE: on freeGLUT, the correct window is always already set. |
| But older versions of GLUT need this call, or else subwindows |
| don't update properly when resizing or damage-painting. |
| */ |
| glutSetWindow( glut_window_id ); |
| |
| /* Set up OpenGL state for widget drawing */ |
| glDisable( GL_DEPTH_TEST ); |
| glCullFace( GL_BACK ); |
| glDisable( GL_CULL_FACE ); |
| glDisable( GL_LIGHTING ); |
| set_current_draw_buffer(); |
| |
| /**** This function is used as a special place to do 'safe' processing, |
| e.g., handling window close requests. |
| That is, we can't close the window directly in the callback, so |
| we set a flag, post a redisplay message (which eventually calls |
| this function), then close the window safely in here. ****/ |
| if ( closing ) { |
| close_internal(); |
| return; |
| } |
| |
| /* if ( TEST_AND( this->flags, GLUI_SUBWINDOW )) |
| check_subwindow_position(); |
| */ |
| |
| win_w = glutGet( GLUT_WINDOW_WIDTH ); |
| win_h = glutGet( GLUT_WINDOW_HEIGHT ); |
| |
| /*** Check here if the window needs resizing ***/ |
| if ( win_w != main_panel->w OR win_h != main_panel->h ) { |
| glutReshapeWindow( main_panel->w, main_panel->h ); |
| return; |
| } |
| |
| /******* Draw GLUI window ******/ |
| glClearColor( (float) bkgd_color.r / 255.0, |
| (float) bkgd_color.g / 255.0, |
| (float) bkgd_color.b / 255.0, |
| 1.0 ); |
| glClear( GL_COLOR_BUFFER_BIT ); /* | GL_DEPTH_BUFFER_BIT ); */ |
| |
| set_ortho_projection(); |
| |
| glMatrixMode( GL_MODELVIEW ); |
| glLoadIdentity(); |
| |
| /*** Rotate image so y increases downward. |
| In normal OpenGL, y increases upward. ***/ |
| glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 ); |
| glRotatef( 180.0, 0.0, 1.0, 0.0 ); |
| glRotatef( 180.0, 0.0, 0.0, 1.0 ); |
| glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 ); |
| |
| // Recursively draw the main panel |
| // main_panel->draw_bkgd_box( 0, 0, win_w, win_h ); |
| main_panel->draw_recursive( 0, 0 ); |
| |
| switch (buffer_mode) { |
| case buffer_front: /* Make sure drawing gets to screen */ |
| glFlush(); |
| break; |
| case buffer_back: /* Bring back buffer to front */ |
| glutSwapBuffers(); |
| break; |
| } |
| } |
| |
| |
| |
| |
| /*************************************** _glutBitmapWidthString() **********/ |
| |
| int _glutBitmapWidthString( void *font, const char *s ) |
| { |
| const char *p = s; |
| int width = 0; |
| |
| while( *p != '\0' ) { |
| width += glutBitmapWidth( font, *p ); |
| p++; |
| } |
| |
| return width; |
| } |
| |
| /************************************ _glutBitmapString *********************/ |
| /* Displays the contents of a string using GLUT's bitmap character function */ |
| /* Does not handle newlines */ |
| |
| void _glutBitmapString( void *font, const char *s ) |
| { |
| const char *p = s; |
| |
| while( *p != '\0' ) { |
| glutBitmapCharacter( font, *p ); |
| p++; |
| } |
| } |
| |
| |
| |
| /****************************** GLUI_Main::reshape() **************/ |
| |
| void GLUI_Main::reshape( int reshape_w, int reshape_h ) |
| { |
| int new_w, new_h; |
| |
| pack_controls(); |
| |
| new_w = main_panel->w;/* + 1; */ |
| new_h = main_panel->h;/* + 1; */ |
| |
| if ( reshape_w != new_w OR reshape_h != new_h ) { |
| this->w = new_w; |
| this->h = new_h; |
| |
| glutReshapeWindow( new_w, new_h ); |
| } |
| else { |
| } |
| |
| if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) { |
| check_subwindow_position(); |
| |
| /***** if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { |
| } |
| else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { |
| } |
| else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { |
| } |
| else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) { |
| } |
| ****/ |
| } |
| |
| glViewport( 0, 0, new_w, new_h ); |
| |
| /* printf( "%d: %d\n", glutGetWindow(), this->flags ); */ |
| |
| glutPostRedisplay(); |
| } |
| |
| |
| /****************************** GLUI_Main::keyboard() **************/ |
| |
| void GLUI_Main::keyboard(unsigned char key, int x, int y) |
| { |
| GLUI_Control *new_control; |
| |
| curr_modifiers = glutGetModifiers(); |
| |
| /*** If it's a tab or shift tab, we don't pass it on to the controls. |
| Instead, we use it to cycle through active controls ***/ |
| if ( key == '\t' AND !mouse_button_down AND |
| (!active_control || !active_control->wants_tabs())) { |
| if ( curr_modifiers & GLUT_ACTIVE_SHIFT ) { |
| new_control = find_prev_control( active_control ); |
| } |
| else { |
| new_control = find_next_control( active_control ); |
| } |
| |
| /* if ( new_control ) |
| printf( "new_control: %s\n", new_control->name ); |
| */ |
| |
| deactivate_current_control(); |
| activate_control( new_control, GLUI_ACTIVATE_TAB ); |
| } |
| else if ( key == ' ' AND active_control |
| AND active_control->spacebar_mouse_click ) { |
| /*** If the user presses the spacebar, and a non-edittext control |
| is active, we send it a mouse down event followed by a mouse up |
| event (simulated mouse-click) ***/ |
| |
| active_control->mouse_down_handler( 0, 0 ); |
| active_control->mouse_up_handler( 0, 0, true ); |
| } else { |
| /*** Pass the keystroke onto the active control, if any ***/ |
| if ( active_control != NULL ) |
| active_control->key_handler( key, curr_modifiers ); |
| } |
| } |
| |
| |
| |
| void GLUI_Main::special_up(int key, int x, int y) |
| { |
| curr_modifiers = glutGetModifiers(); |
| |
| /*** Pass the keystroke onto the active control, if any ***/ |
| if ( active_control != NULL ) |
| active_control->special_up_handler( key, glutGetModifiers() ); |
| } |
| |
| |
| /****************************** GLUI_Main::special() **************/ |
| |
| void GLUI_Main::special(int key, int x, int y) |
| { |
| curr_modifiers = glutGetModifiers(); |
| |
| /*** Pass the keystroke onto the active control, if any ***/ |
| if ( active_control != NULL ) |
| active_control->special_handler( key, glutGetModifiers() ); |
| } |
| |
| |
| |
| /****************************** GLUI_Main::mouse() **************/ |
| |
| void GLUI_Main::mouse(int button, int state, int x, int y) |
| { |
| int callthrough; |
| GLUI_Control *control; |
| |
| /* printf( "MOUSE: %d %d\n", button, state ); */ |
| |
| callthrough = true; |
| |
| curr_modifiers = glutGetModifiers(); |
| |
| if ( button == GLUT_LEFT ) { |
| control = find_control( x, y ); |
| |
| /*if ( control ) printf( "control: %s\n", control->name.c_str() ); */ |
| |
| if ( mouse_button_down AND active_control != NULL AND |
| state == GLUT_UP ) |
| { |
| /** We just released the mouse, which was depressed at some control **/ |
| |
| callthrough = active_control-> |
| mouse_up_handler( x, y, control==active_control); |
| glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); |
| |
| if ( active_control AND |
| active_control->active_type == GLUI_CONTROL_ACTIVE_MOUSEDOWN AND 0) |
| { |
| /*** This is a control that needs to be deactivated when the |
| mouse button is released ****/ |
| deactivate_current_control(); |
| } |
| } |
| else { |
| if ( control ) { |
| if ( NOT mouse_button_down AND state == GLUT_DOWN ) { |
| /*** We just pressed the mouse down at some control ***/ |
| |
| if ( active_control != control ) { |
| if ( active_control != NULL ) { |
| /** There is an active control still - deactivate it ***/ |
| deactivate_current_control(); |
| } |
| } |
| |
| if ( control->enabled ) { |
| activate_control( control, GLUI_ACTIVATE_MOUSE ); |
| callthrough = control->mouse_down_handler( x, y ); |
| } |
| } |
| } |
| } |
| |
| if ( state == GLUT_DOWN ) |
| mouse_button_down = true; |
| else if ( state == GLUT_UP ) |
| mouse_button_down = false; |
| } |
| |
| /** |
| NO CALLTHROUGH NEEDED FOR MOUSE EVENTS |
| if ( callthrough AND glut_mouse_CB ) |
| glut_mouse_CB( button, state, x, y ); |
| **/ |
| |
| callthrough=callthrough; /* To get rid of compiler warnings */ |
| } |
| |
| |
| /****************************** GLUI_Main::motion() **************/ |
| |
| void GLUI_Main::motion(int x, int y) |
| { |
| int callthrough; |
| GLUI_Control *control; |
| |
| /* printf( "MOTION: %d %d\n", x, y ); */ |
| |
| callthrough = true; |
| |
| control = find_control(x,y); |
| |
| if ( mouse_button_down AND active_control != NULL ) { |
| callthrough = |
| active_control->mouse_held_down_handler(x,y,control==active_control); |
| } |
| |
| /** |
| NO CALLTHROUGH NEEDED FOR MOUSE EVENTS |
| |
| if ( callthrough AND glut_motion_CB ) |
| glut_motion_CB(x,y); |
| **/ |
| |
| callthrough=callthrough; /* To get rid of compiler warnings */ |
| } |
| |
| |
| /*********************** GLUI_Main::passive_motion() **************/ |
| |
| void GLUI_Main::passive_motion(int x, int y) |
| { |
| GLUI_Control *control; |
| |
| control = find_control( x, y ); |
| |
| /* printf( "%p %p\n", control, mouse_over_control ); */ |
| |
| if ( control != mouse_over_control ) { |
| if ( mouse_over_control ) { |
| mouse_over_control->mouse_over( false, x, y ); |
| } |
| |
| if ( control ) { |
| control->mouse_over( true, x, y ); |
| mouse_over_control = control; |
| } |
| } |
| |
| /* |
| if ( curr_cursor != GLUT_CURSOR_INHERIT ) { |
| curr_cursor = GLUT_CURSOR_INHERIT; |
| glutSetCursor( GLUT_CURSOR_INHERIT ); |
| }*/ |
| |
| } |
| |
| |
| /****************************** GLUI_Main::entry() **************/ |
| |
| void GLUI_Main::entry(int state) |
| { |
| /*if ( NOT active_control OR ( active_control AND ( active_control->type == GLUI_CONTROL_EDITTEXT |
| OR active_control->type == GLUI_CONTROL_SPINNER) ) )*/ |
| glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); |
| } |
| |
| |
| /****************************** GLUI_Main::visibility() **************/ |
| |
| void GLUI_Main::visibility(int state) |
| { |
| } |
| |
| |
| /****************************** GLUI_Main::idle() **************/ |
| |
| void GLUI_Main::idle(void) |
| { |
| /*** Pass the idle event onto the active control, if any ***/ |
| |
| /* printf( "IDLE \t" ); */ |
| |
| if ( active_control != NULL ) { |
| /* First we check if the control actually needs the idle right now. |
| Otherwise, let's avoid wasting cycles and OpenGL context switching */ |
| |
| if ( active_control->needs_idle() ) { |
| /*** Set the current glut window to the glui window */ |
| /*** But don't change the window if we're already at that window ***/ |
| |
| if ( glut_window_id > 0 AND glutGetWindow() != glut_window_id ) { |
| glutSetWindow( glut_window_id ); |
| } |
| |
| active_control->idle(); |
| } |
| } |
| } |
| |
| int GLUI_Main::needs_idle( void ) |
| { |
| return active_control != NULL && active_control->needs_idle(); |
| } |
| |
| |
| /******************************************* GLUI_Main::find_control() ******/ |
| |
| GLUI_Control *GLUI_Main::find_control( int x, int y ) |
| { |
| GLUI_Control *node, *last_container; |
| |
| last_container = NULL; |
| |
| node = main_panel; |
| while( node != NULL ) { |
| if ( !node->dynamicCastGLUI_Column() AND |
| PT_IN_BOX( x, y, |
| node->x_abs, node->x_abs + node->w, |
| node->y_abs, node->y_abs + node->h ) |
| ) |
| { |
| /*** Point is inside current node ***/ |
| |
| if ( node->first_child() == NULL ) { |
| /*** SPECIAL CASE: for edittext boxes, we make sure click is |
| in box, and not on name string. This should be generalized |
| for all controls later... ***/ |
| if ( node->dynamicCastGLUI_EditText() ) { |
| if ( x < node->x_abs + ((GLUI_EditText*)node)->text_x_offset ) |
| return (GLUI_Control*) node->parent(); |
| } |
| |
| return node; /* point is inside this node, and node has no children, |
| so return this node as the selected node */ |
| } |
| else { |
| /*** This is a container class ***/ |
| last_container = node; |
| node = (GLUI_Control*) node->first_child(); /* Descend into child */ |
| } |
| |
| } |
| else { |
| node = (GLUI_Control*) node->next(); |
| } |
| } |
| |
| /** No leaf-level nodes found to accept the mouse click, so |
| return the last container control found which DOES accept the click **/ |
| |
| if ( last_container ) { |
| /* printf( "ctrl: '%s'\n", last_container->name ); */ |
| |
| return last_container; |
| } |
| else { |
| return NULL; |
| } |
| } |
| |
| |
| /************************************* GLUI_Main::pack_controls() ***********/ |
| |
| void GLUI_Main::pack_controls( void ) |
| { |
| main_panel->pack(0,0); |
| |
| /**** Now align controls within their bounds ****/ |
| align_controls( main_panel ); |
| |
| /*** If this is a subwindow, expand panel to fit parent window ***/ |
| if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) { |
| int parent_h, parent_w; |
| int orig_window; |
| |
| orig_window = glutGetWindow(); |
| glutSetWindow( this->top_level_glut_window_id ); |
| parent_h = glutGet( GLUT_WINDOW_HEIGHT ); |
| parent_w = glutGet( GLUT_WINDOW_WIDTH ); |
| |
| glutSetWindow( orig_window ); |
| |
| /* printf( "%d %d\n", parent_h, parent_w ); */ |
| |
| if ( 1 ) { |
| if ( TEST_AND(this->flags,GLUI_SUBWINDOW_TOP )) { |
| main_panel->w = MAX( main_panel->w, parent_w ); |
| } |
| else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { |
| main_panel->h = MAX( main_panel->h, parent_h ); |
| } |
| else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) { |
| main_panel->w = MAX( main_panel->w, parent_w ); |
| } |
| else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) { |
| main_panel->h = MAX( main_panel->h, parent_h ); |
| } |
| } |
| } |
| |
| this->w = main_panel->w; |
| this->h = main_panel->h; |
| } |
| |
| |
| /************************************ GLUI_Main::align_controls() **********/ |
| |
| void GLUI_Main::align_controls( GLUI_Control *control ) |
| { |
| GLUI_Control *child; |
| |
| control->align(); |
| |
| child = (GLUI_Control*) control->first_child(); |
| |
| while( child != NULL ) { |
| align_controls( child ); |
| |
| child = (GLUI_Control*)child->next(); |
| } |
| } |
| |
| |
| |
| /*********************************** GLUI::set_main_gfx_window() ************/ |
| |
| void GLUI::set_main_gfx_window( int window_id ) |
| { |
| main_gfx_window_id = window_id; |
| } |
| |
| |
| /********************************* GLUI_Main::post_update_main_gfx() ********/ |
| |
| void GLUI_Main::post_update_main_gfx( void ) |
| { |
| int old_window; |
| |
| if ( main_gfx_window_id > 0 ) { |
| old_window = glutGetWindow(); |
| glutSetWindow( main_gfx_window_id ); |
| glutPostRedisplay(); |
| if( old_window > 0 ) |
| glutSetWindow( old_window ); |
| } |
| } |
| |
| /********************************* GLUI_Main::should_redraw_now() ********/ |
| /** Return true if this control should redraw itself immediately (front buffer); |
| Or queue up a redraw and return false if it shouldn't (back buffer). |
| |
| Called from GLUI_Control::redraw. |
| */ |
| bool GLUI_Main::should_redraw_now(GLUI_Control *ctl) |
| { |
| switch (buffer_mode) { |
| case buffer_front: return true; /* always draw in front-buffer mode */ |
| case buffer_back: { |
| int orig = ctl->set_to_glut_window(); |
| glutPostRedisplay(); /* redraw soon */ |
| ctl->restore_window(orig); |
| return false; /* don't draw now. */ |
| } |
| } |
| return false; /* never executed */ |
| } |
| |
| /********************************* GLUI_Main::set_current_draw_buffer() ********/ |
| |
| int GLUI_Main::set_current_draw_buffer( void ) |
| { |
| /* Save old buffer */ |
| GLint state; |
| glGetIntegerv( GL_DRAW_BUFFER, &state ); |
| /* Switch to new buffer */ |
| switch (buffer_mode) { |
| case buffer_front: glDrawBuffer(GL_FRONT); break; |
| case buffer_back: glDrawBuffer(GL_BACK); break; /* might not be needed... */ |
| } |
| return (int)state; |
| } |
| |
| |
| /********************************* GLUI_Main::restore_draw_buffer() **********/ |
| |
| void GLUI_Main::restore_draw_buffer( int buffer_state ) |
| { |
| glDrawBuffer( buffer_state ); |
| } |
| |
| |
| /******************************************** GLUI_Main::GLUI_Main() ********/ |
| |
| GLUI_Main::GLUI_Main( void ) |
| { |
| mouse_button_down = false; |
| w = 0; |
| h = 0; |
| active_control = NULL; |
| mouse_over_control = NULL; |
| main_gfx_window_id = -1; |
| glut_window_id = -1; |
| curr_modifiers = 0; |
| closing = false; |
| parent_window = -1; |
| glui_id = GLUI_Master.glui_id_counter; |
| GLUI_Master.glui_id_counter++; |
| |
| font = GLUT_BITMAP_HELVETICA_12; |
| curr_cursor = GLUT_CURSOR_LEFT_ARROW; |
| |
| int r=200, g=200, b=200; |
| bkgd_color.set( r,g,b ); |
| bkgd_color_f[0] = r / 255.0; |
| bkgd_color_f[1] = g / 255.0; |
| bkgd_color_f[2] = b / 255.0; |
| |
| /*** Create the main panel ***/ |
| main_panel = new GLUI_Panel; |
| main_panel->set_int_val( GLUI_PANEL_NONE ); |
| main_panel->glui = (GLUI*) this; |
| main_panel->name = "\0"; |
| } |
| |
| /************************************ GLUI_Main::draw_raised_box() **********/ |
| |
| void GLUI_Main::draw_raised_box( int x, int y, int w, int h ) |
| { |
| w = w+x; |
| h = h+y; |
| |
| glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b ); |
| glBegin( GL_LINE_LOOP ); |
| glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 ); |
| glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 ); |
| glEnd(); |
| |
| glColor3d( 1.0, 1.0, 1.0 ); |
| glBegin( GL_LINE_STRIP ); |
| glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y ); |
| glEnd(); |
| |
| glColor3d( 0.0, 0.0, 0.0 ); |
| glBegin( GL_LINE_STRIP ); |
| glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h ); |
| glEnd(); |
| |
| glColor3d( .5, .5, .5 ); |
| glBegin( GL_LINE_STRIP ); |
| glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 ); |
| glEnd(); |
| } |
| |
| |
| /************************************ GLUI_Main::draw_lowered_box() **********/ |
| /* Not quite perfect... **/ |
| |
| void GLUI_Main::draw_lowered_box( int x, int y, int w, int h ) |
| { |
| w = w+x; |
| h = h+y; |
| |
| glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b ); |
| glBegin( GL_LINE_LOOP ); |
| glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 ); |
| glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 ); |
| glEnd(); |
| |
| glColor3d( 0.0, 0.0, 0.0 ); |
| glBegin( GL_LINE_STRIP ); |
| glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y ); |
| glEnd(); |
| |
| glColor3d( 1.0, 1.0, 1.0 ); |
| glBegin( GL_LINE_STRIP ); |
| glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h ); |
| glEnd(); |
| |
| glColor3d( .5, .5, .5 ); |
| glBegin( GL_LINE_STRIP ); |
| glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 ); |
| glEnd(); |
| } |
| |
| |
| /************************************* GLUI_Main::activate_control() *********/ |
| |
| void GLUI_Main::activate_control( GLUI_Control *control, int how ) |
| { |
| /** Are we not activating a control in the same window as the |
| previous active control? */ |
| if ( GLUI_Master.active_control_glui AND |
| this != (GLUI_Main*) GLUI_Master.active_control_glui ) { |
| GLUI_Master.active_control_glui->deactivate_current_control(); |
| } |
| |
| /******* Now activate it *****/ |
| if ( control != NULL AND control->can_activate AND control->enabled ) { |
| active_control = control; |
| |
| control->activate(how); |
| |
| /*if ( NOT active_control->is_container OR */ |
| /* active_control->type == GLUI_CONTROL_ROLLOUT) { */ |
| active_control->redraw(); |
| /*} */ |
| } |
| else { |
| active_control = NULL; |
| } |
| |
| /* printf( "activate: %d\n", glutGetWindow() ); */ |
| GLUI_Master.active_control = active_control; |
| GLUI_Master.active_control_glui = (GLUI*) this; |
| } |
| |
| |
| /************************* GLUI_Main::deactivate_current_control() **********/ |
| |
| void GLUI_Main::deactivate_current_control( void ) |
| { |
| int orig; |
| |
| if ( active_control != NULL ) { |
| orig = active_control->set_to_glut_window(); |
| |
| active_control->deactivate(); |
| |
| /** If this isn't a container control, then redraw it in its |
| deactivated state. Container controls, such as panels, look |
| the same activated or not **/ |
| |
| /*if ( NOT active_control->is_container OR */ |
| /* active_control->type == GLUI_CONTROL_ROLLOUT ) { */ |
| active_control->redraw(); |
| /*} */ |
| |
| active_control->restore_window( orig ); |
| |
| active_control = NULL; |
| } |
| |
| /* printf( "deactivate: %d\n", glutGetWindow() ); */ |
| GLUI_Master.active_control = NULL; |
| GLUI_Master.active_control_glui = NULL; |
| } |
| |
| |
| /****************************** GLUI_Main::find_next_control() **************/ |
| |
| GLUI_Control *GLUI_Main::find_next_control_( GLUI_Control *control ) |
| { |
| /*** THIS IS NOT find_next_control()! This is an unused older |
| version (look at the underscore at the end) ***/ |
| |
| if ( control == NULL ) |
| return find_next_control_rec( main_panel ); |
| else |
| return find_next_control_rec( control ); |
| } |
| |
| /****************************** GLUI_Main::find_next_control() **************/ |
| |
| GLUI_Control *GLUI_Main::find_next_control_rec( GLUI_Control *control ) |
| { |
| GLUI_Control *child = NULL, *rec_control, *sibling; |
| |
| /*** Recursively investigate children ***/ |
| child = (GLUI_Control*) control->first_child(); |
| if ( child ) { |
| /*** If we can activate the first child, then do so ***/ |
| if ( child->can_activate AND child->enabled ) |
| return child; |
| else /*** Recurse into first child ***/ |
| rec_control = find_next_control_rec( child ); |
| |
| if ( rec_control ) |
| return rec_control; |
| } |
| |
| /*** At this point, either we don't have children, or the child cannot |
| be activated. So let's try the next sibling ***/ |
| |
| sibling = (GLUI_Control*) control->next(); |
| if ( sibling ) { |
| if ( sibling->can_activate AND sibling->enabled ) |
| return sibling; |
| else /*** Recurse into sibling ***/ |
| rec_control = find_next_control_rec( sibling ); |
| |
| if ( rec_control ) |
| return rec_control; |
| } |
| |
| return NULL; |
| } |
| |
| |
| /****************************** GLUI_Main::find_next_control() **************/ |
| |
| GLUI_Control *GLUI_Main::find_next_control( GLUI_Control *control ) |
| { |
| GLUI_Control *tmp_control = NULL; |
| int back_up; |
| |
| if ( control == NULL ) |
| control = main_panel; |
| |
| while( control != NULL ) { |
| /** see if this control has a child **/ |
| tmp_control = (GLUI_Control*) control->first_child(); |
| |
| if ( tmp_control != NULL ) { |
| if ( tmp_control->can_activate AND tmp_control->enabled ) |
| return tmp_control; |
| |
| control = tmp_control; /* Descend into child */ |
| continue; |
| } |
| |
| /*** At this point, control has no children ***/ |
| |
| /** see if this control has a next sibling **/ |
| tmp_control = (GLUI_Control*) control->next(); |
| |
| if ( tmp_control != NULL ) { |
| if ( tmp_control->can_activate AND tmp_control->enabled ) |
| return tmp_control; |
| |
| control = tmp_control; |
| continue; |
| } |
| |
| /** back up until we find a sibling of an ancestor **/ |
| back_up = true; |
| while ( control->parent() AND back_up ) { |
| control = (GLUI_Control*) control->parent(); |
| |
| if ( control->next() ) { |
| control = (GLUI_Control*) control->next(); |
| if ( control->can_activate AND control->enabled ) |
| return control; |
| else |
| back_up = false; |
| |
| /*** if ( control->is_container ) { |
| tmp_control = control; |
| control = NULL; |
| break; |
| } |
| else { |
| back_up = false; |
| } |
| ***/ |
| } |
| } |
| |
| /** Check if we've cycled back to the top... if so, return NULL **/ |
| if ( control == main_panel ) { |
| return NULL; |
| } |
| } |
| /* |
| if ( tmp_control != NULL AND tmp_control->can_activate AND |
| tmp_control->enabled ) { |
| return tmp_control; |
| }*/ |
| |
| return NULL; |
| } |
| |
| |
| /****************************** GLUI_Main::find_prev_control() **************/ |
| |
| GLUI_Control *GLUI_Main::find_prev_control( GLUI_Control *control ) |
| { |
| GLUI_Control *tmp_control, *next_control; |
| |
| if ( control == NULL ) { /* here we find the last valid control */ |
| next_control = main_panel; |
| |
| do { |
| tmp_control = next_control; |
| next_control = find_next_control( tmp_control ); |
| } while( next_control != NULL ); |
| |
| return tmp_control; |
| } |
| else { /* here we find the actual previous control */ |
| next_control = main_panel; |
| |
| do { |
| tmp_control = next_control; |
| next_control = find_next_control( tmp_control ); |
| } while( next_control != NULL AND next_control != control ); |
| |
| if ( next_control == NULL OR tmp_control == main_panel ) |
| return NULL; |
| else |
| return tmp_control; |
| } |
| } |
| |
| /************************* GLUI_Master_Object::set_glutIdleFunc() ***********/ |
| |
| void GLUI_Master_Object::set_glutIdleFunc(void (*f)(void)) |
| { |
| glut_idle_CB = f; |
| GLUI_Master.glui_setIdleFuncIfNecessary(); |
| } |
| |
| |
| /**************************************** GLUI::disable() ********************/ |
| |
| void GLUI::disable( void ) |
| { |
| deactivate_current_control(); |
| main_panel->disable(); |
| } |
| |
| |
| /******************************************** GLUI::sync_live() **************/ |
| |
| void GLUI::sync_live( void ) |
| { |
| main_panel->sync_live(true, true); |
| } |
| |
| |
| /********************************* GLUI_Master_Object::sync_live_all() *****/ |
| |
| void GLUI_Master_Object::sync_live_all( void ) |
| { |
| GLUI *glui; |
| |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while( glui ) { |
| |
| glui->sync_live(); /** sync it **/ |
| |
| glui = (GLUI*) glui->next(); |
| } |
| } |
| |
| |
| /************************************* GLUI_Master_Object::close() **********/ |
| |
| void GLUI_Master_Object::close_all( void ) |
| { |
| GLUI *glui; |
| |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while( glui ) { |
| |
| glui->close(); /** Set flag to close **/ |
| |
| glui = (GLUI*) glui->next(); |
| } |
| } |
| |
| |
| /************************************* GLUI_Main::close_internal() **********/ |
| |
| void GLUI_Main::close_internal( void ) |
| { |
| glutDestroyWindow(glutGetWindow()); /** Close this window **/ |
| |
| this->unlink(); |
| |
| if ( GLUI_Master.active_control_glui == this ) { |
| GLUI_Master.active_control = NULL; |
| GLUI_Master.active_control_glui = NULL; |
| } |
| |
| if ( parent_window != -1 ) { |
| glutSetWindow( parent_window ); |
| int win_w = glutGet( GLUT_WINDOW_WIDTH ); |
| int win_h = glutGet( GLUT_WINDOW_HEIGHT ); |
| glutReshapeWindow(win_w+1, win_h); |
| glutReshapeWindow(win_w-1, win_h); |
| } |
| |
| delete this->main_panel; |
| |
| delete this; |
| } |
| |
| |
| /************************************************** GLUI::close() **********/ |
| |
| void GLUI::close( void ) |
| { |
| int old_glut_window; |
| |
| closing = true; |
| |
| old_glut_window = glutGetWindow(); |
| glutSetWindow( get_glut_window_id() ); |
| glutPostRedisplay(); |
| |
| glutSetWindow( old_glut_window ); |
| } |
| |
| |
| /************************** GLUI_Main::check_subwindow_position() **********/ |
| |
| void GLUI_Main::check_subwindow_position( void ) |
| { |
| /*** Reposition this window if subwindow ***/ |
| if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) { |
| |
| int parent_w, parent_h, new_x, new_y; |
| int old_window = glutGetWindow(); |
| |
| glutSetWindow( glut_window_id ); |
| |
| glutSetWindow( glutGet( GLUT_WINDOW_PARENT )); |
| parent_w = glutGet( GLUT_WINDOW_WIDTH ); |
| parent_h = glutGet( GLUT_WINDOW_HEIGHT ); |
| |
| glutSetWindow( glut_window_id ); |
| |
| if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) { |
| new_x = parent_w - this->w; |
| new_y = 0; |
| } |
| else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) { |
| new_x = 0; |
| new_y = 0; |
| } |
| else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) { |
| new_x = 0; |
| new_y = parent_h - this->h; |
| } |
| else { /*** GLUI_SUBWINDOW_TOP ***/ |
| new_x = 0; |
| new_y = 0; |
| } |
| |
| /** Now make adjustments based on presence of other subwindows **/ |
| GLUI *curr_glui; |
| curr_glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while( curr_glui ) { |
| if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND |
| curr_glui->parent_window == this->parent_window ) { |
| |
| if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) { |
| } |
| else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) { |
| } |
| else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) { |
| } |
| else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) AND |
| ( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) OR |
| TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) ) ) { |
| /** If we are a RIGHT or LEFT subwindow, and there exists some |
| TOP subwindow, bump our position down **/ |
| |
| new_y += curr_glui->h; |
| } |
| |
| /** CHeck multiple subwins at same position **/ |
| /** We check the glui_id's: only the glui with the higher |
| ID number (meaning it was created later) gets bumped over **/ |
| if ( curr_glui != this AND this->glui_id > curr_glui->glui_id ) { |
| if ( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) AND |
| TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) { |
| new_x += curr_glui->w; |
| } |
| else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_TOP ) AND |
| TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) { |
| new_y += curr_glui->h; |
| } |
| else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_BOTTOM ) AND |
| TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) { |
| new_y -= curr_glui->h; |
| } |
| else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) AND |
| TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) { |
| new_x -= curr_glui->w; |
| } |
| |
| } |
| } |
| |
| curr_glui = (GLUI*) curr_glui->next(); |
| } |
| |
| |
| |
| CLAMP( new_x, 0, new_x ); |
| CLAMP( new_y, 0, new_y ); |
| |
| glutPositionWindow( new_x, new_y ); |
| /* glutPostRedisplay(); */ |
| |
| glutSetWindow( old_window ); |
| } |
| } |
| |
| |
| /********************************* GLUI_Master_Object::reshape() **********/ |
| /* This gets called by the user from a GLUT reshape callback. So we look */ |
| /* for subwindows that belong to the current window */ |
| |
| void GLUI_Master_Object::reshape( void ) |
| { |
| GLUI *glui; |
| int current_window; |
| |
| current_window = glutGetWindow(); |
| |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while( glui ) { |
| if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND |
| glui->parent_window == current_window ) { |
| glutSetWindow( glui->get_glut_window_id()); |
| glui->check_subwindow_position(); |
| } |
| |
| glui = (GLUI*) glui->next(); |
| } |
| |
| glutSetWindow(current_window); |
| } |
| |
| |
| /**************************** GLUI_Master_Object::set_glutReshapeFunc() *****/ |
| |
| void GLUI_Master_Object::set_glutReshapeFunc(void (*f)(int width, int height)) |
| { |
| glutReshapeFunc( glui_reshape_func ); |
| add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_RESHAPE, (void*) f); |
| } |
| |
| |
| /**************************** GLUI_Master_Object::set_glutKeyboardFunc() ****/ |
| |
| void GLUI_Master_Object::set_glutKeyboardFunc(void (*f)(unsigned char key, |
| int x, int y)) |
| { |
| glutKeyboardFunc( glui_keyboard_func ); |
| add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_KEYBOARD, (void*) f); |
| } |
| |
| |
| /*********************** GLUI_Master_Object::set_glutSpecialFunc() **********/ |
| |
| |
| |
| void GLUI_Master_Object::set_glutSpecialUpFunc(void (*f)(int key, |
| int x, int y)) |
| { |
| glutSpecialUpFunc( glui_special_up_func ); |
| add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL_UP, (void*) f); |
| } |
| |
| |
| void GLUI_Master_Object::set_glutSpecialFunc(void (*f)(int key, |
| int x, int y)) |
| { |
| glutSpecialFunc( glui_special_func ); |
| add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL, (void*) f); |
| } |
| |
| |
| /*********************** GLUI_Master_Object::set_glutMouseFunc() **********/ |
| |
| void GLUI_Master_Object::set_glutMouseFunc(void (*f)(int button, int state, |
| int x, int y)) |
| { |
| glutMouseFunc( glui_mouse_func ); |
| add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_MOUSE, (void*) f); |
| } |
| |
| |
| /****************************** glui_parent_window_reshape_func() **********/ |
| /* This is the reshape callback for a window that contains subwindows */ |
| |
| void glui_parent_window_reshape_func( int w, int h ) |
| { |
| int current_window; |
| GLUI *glui; |
| int first = true; |
| |
| /* printf( "glui_parent_window_reshape_func: %d\n", glutGetWindow() ); */ |
| |
| current_window = glutGetWindow(); |
| |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while( glui ) { |
| if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND |
| glui->parent_window == current_window ) { |
| glutSetWindow( glui->get_glut_window_id()); |
| glui->check_subwindow_position(); |
| glutSetWindow( current_window ); |
| |
| if ( first ) { |
| if (glui->glut_reshape_CB) glui->glut_reshape_CB( w, h ); |
| |
| first = false; |
| } |
| } |
| |
| glui = (GLUI*) glui->next(); |
| } |
| } |
| |
| |
| /****************************** glui_parent_window_keyboard_func() **********/ |
| |
| void glui_parent_window_keyboard_func(unsigned char key, int x, int y) |
| { |
| /* printf( "glui_parent_window_keyboard_func: %d\n", glutGetWindow() ); */ |
| |
| int current_window; |
| GLUI *glui; |
| |
| current_window = glutGetWindow(); |
| |
| if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) { |
| glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() ); |
| |
| GLUI_Master.active_control_glui->keyboard(key,x,y); |
| |
| glutSetWindow( current_window ); |
| } |
| else { |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while( glui ) { |
| if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND |
| glui->parent_window == current_window AND |
| glui->glut_keyboard_CB ) |
| { |
| glui->glut_keyboard_CB( key, x, y ); |
| break; |
| } |
| |
| glui = (GLUI*) glui->next(); |
| } |
| } |
| } |
| |
| |
| /****************************** glui_parent_window_special_func() **********/ |
| |
| void glui_parent_window_special_func(int key, int x, int y) |
| { |
| /*printf( "glui_parent_window_special_func: %d\n", glutGetWindow() ); */ |
| |
| int current_window; |
| GLUI *glui; |
| |
| /** If clicking in the main area of a window w/subwindows, |
| deactivate any current control **/ |
| if ( GLUI_Master.active_control_glui != NULL ) |
| GLUI_Master.active_control_glui->deactivate_current_control(); |
| |
| /*** Now pass on the mouse event ***/ |
| |
| current_window = glutGetWindow(); |
| |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while( glui ) { |
| if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND |
| glui->parent_window == current_window ) |
| { |
| glutSetWindow( glui->get_glut_window_id()); |
| if (glui->glut_special_CB) glui->glut_special_CB( key, x, y ); |
| break; |
| } |
| |
| glui = (GLUI*) glui->next(); |
| } |
| } |
| |
| |
| /****************************** glui_parent_window_mouse_func() **********/ |
| |
| void glui_parent_window_mouse_func(int button, int state, int x, int y) |
| { |
| int current_window; |
| GLUI *glui; |
| |
| /** If clicking in the main area of a window w/subwindows, |
| deactivate any current control **/ |
| if ( GLUI_Master.active_control_glui != NULL ) |
| GLUI_Master.active_control_glui->deactivate_current_control(); |
| |
| |
| /*** Now pass on the mouse event ***/ |
| |
| current_window = glutGetWindow(); |
| |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| while( glui ) { |
| if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND |
| glui->parent_window == current_window AND |
| glui->glut_mouse_CB) |
| { |
| glutSetWindow( glui->get_glut_window_id()); |
| glui->glut_mouse_CB( button, state, x, y ); |
| break; |
| } |
| |
| glui = (GLUI*) glui->next(); |
| } |
| } |
| |
| |
| /************************** GLUI_Master_Object::find_glut_window() **********/ |
| |
| GLUI_Glut_Window *GLUI_Master_Object::find_glut_window( int window_id ) |
| { |
| GLUI_Glut_Window *window; |
| |
| window = (GLUI_Glut_Window*) glut_windows.first_child(); |
| while( window ) { |
| if ( window->glut_window_id == window_id ) |
| return window; |
| |
| window = (GLUI_Glut_Window*) window->next(); |
| } |
| |
| /*** Window not found - return NULL ***/ |
| return NULL; |
| } |
| |
| |
| /******************** GLUI_Master_Object::add_cb_to_glut_window() **********/ |
| |
| void GLUI_Master_Object::add_cb_to_glut_window(int window_id, |
| int cb_type,void *cb) |
| { |
| GLUI_Glut_Window *window; |
| |
| window = find_glut_window( window_id ); |
| if ( NOT window ) { |
| /*** Allocate new window structure ***/ |
| |
| window = new GLUI_Glut_Window; |
| window->glut_window_id = window_id; |
| window->link_this_to_parent_last( (GLUI_Node*) &this->glut_windows ); |
| } |
| |
| switch( cb_type ) { |
| case GLUI_GLUT_RESHAPE: |
| window->glut_reshape_CB = (void(*)(int,int)) cb; |
| break; |
| case GLUI_GLUT_DISPLAY: |
| window->glut_display_CB = (void(*)()) cb; |
| break; |
| case GLUI_GLUT_KEYBOARD: |
| window->glut_keyboard_CB = (void(*)(unsigned char,int,int)) cb; |
| break; |
| case GLUI_GLUT_SPECIAL: |
| window->glut_special_CB = (void(*)(int,int,int)) cb; |
| break; |
| case GLUI_GLUT_SPECIAL_UP: |
| window->glut_special_up_CB = (void(*)(int,int,int)) cb; |
| break; |
| case GLUI_GLUT_MOUSE: |
| window->glut_mouse_CB = (void(*)(int,int,int,int)) cb; |
| break; |
| case GLUI_GLUT_MOTION: |
| window->glut_motion_CB = (void(*)(int,int)) cb; |
| break; |
| case GLUI_GLUT_PASSIVE_MOTION: |
| window->glut_passive_motion_CB = (void(*)(int,int)) cb; |
| break; |
| case GLUI_GLUT_ENTRY: |
| window->glut_entry_CB = (void(*)(int)) cb; |
| break; |
| case GLUI_GLUT_VISIBILITY: |
| window->glut_visibility_CB= (void(*)(int)) cb; |
| break; |
| } |
| } |
| |
| |
| /************* GLUI_Master_Object::set_left_button_glut_menu_control() *****/ |
| |
| void GLUI_Master_Object::set_left_button_glut_menu_control( |
| GLUI_Control *control ) |
| { |
| curr_left_button_glut_menu = control; |
| } |
| |
| |
| /******************************* GLUI_Main::set_ortho_projection() **********/ |
| |
| void GLUI_Main::set_ortho_projection( void ) |
| { |
| int win_h, win_w; |
| |
| win_w = glutGet( GLUT_WINDOW_WIDTH ); |
| win_h = glutGet( GLUT_WINDOW_HEIGHT ); |
| |
| glMatrixMode( GL_PROJECTION ); |
| glLoadIdentity(); |
| /* gluOrtho2D( 0.0, (float) win_w, 0.0, (float) win_h ); */ |
| glOrtho( 0.0, (float)win_w, 0.0, (float) win_h, -1000.0, 1000.0 ); |
| |
| glMatrixMode( GL_MODELVIEW ); |
| |
| return; /****-----------------------------------------------***/ |
| |
| glMatrixMode( GL_MODELVIEW ); |
| glLoadIdentity(); |
| |
| /*** Rotate image so y increases upwards, contrary to OpenGL axes ***/ |
| glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 ); |
| glRotatef( 180.0, 0.0, 1.0, 0.0 ); |
| glRotatef( 180.0, 0.0, 0.0, 1.0 ); |
| glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 ); |
| } |
| |
| |
| /******************************* GLUI_Main::set_viewport() **********/ |
| |
| void GLUI_Main::set_viewport( void ) |
| { |
| glViewport( 0, 0, main_panel->w, main_panel->h ); |
| } |
| |
| |
| /****************************** GLUI_Main::refresh() ****************/ |
| |
| void GLUI_Main::refresh( void ) |
| { |
| int orig; |
| |
| /****** GLUI_Glut_Window *glut_window; |
| int current_window; |
| current_window = glutGetWindow(); |
| glut_window = GLUI_Master.find_glut_window( current_window ); |
| if ( glut_window ) { |
| glut_window->glut_reshape_CB(w,h); |
| ******/ |
| |
| orig = glutGetWindow(); |
| |
| pack_controls(); |
| |
| if ( glut_window_id > 0 ) |
| glutSetWindow( glut_window_id ); |
| |
| |
| if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) { |
| /*** GLUI subwindow ***/ |
| |
| check_subwindow_position(); |
| } |
| else { |
| /*** Standalone GLUI window ***/ |
| |
| glutReshapeWindow( this->h, this->w ); |
| |
| } |
| |
| glutPostRedisplay(); |
| glutSetWindow( orig); |
| } |
| |
| |
| |
| /***************** GLUI_Master_Object::get_main_gfx_viewport() ***********/ |
| |
| void GLUI_Master_Object::get_viewport_area( int *x, int *y, |
| int *w, int *h ) |
| { |
| GLUI *curr_glui; |
| int curr_x, curr_y, curr_w, curr_h; |
| int curr_window; |
| |
| curr_window = glutGetWindow(); |
| curr_x = 0; |
| curr_y = 0; |
| curr_w = glutGet( GLUT_WINDOW_WIDTH ); |
| curr_h = glutGet( GLUT_WINDOW_HEIGHT ); |
| |
| curr_glui = (GLUI*) gluis.first_child(); |
| while( curr_glui ) { |
| if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND |
| curr_glui->parent_window == curr_window ) { |
| |
| /* printf( "%s -> %d %d %d\n", curr_glui->window_name.c_str(), curr_glui->flags, |
| curr_glui->w, curr_glui->h );*/ |
| |
| if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) { |
| curr_x += curr_glui->w; |
| curr_w -= curr_glui->w; |
| } |
| else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) { |
| curr_y += curr_glui->h; |
| curr_h -= curr_glui->h; |
| } |
| else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) { |
| curr_w -= curr_glui->w; |
| } |
| else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) { |
| curr_h -= curr_glui->h; |
| } |
| } |
| |
| curr_glui = (GLUI*) curr_glui->next(); |
| } |
| |
| curr_x = MAX( 0, curr_x ); |
| curr_y = MAX( 0, curr_y ); |
| curr_w = MAX( 0, curr_w ); |
| curr_h = MAX( 0, curr_h ); |
| |
| *x = curr_x; |
| *y = curr_y; |
| *w = curr_w; |
| *h = curr_h; |
| } |
| |
| |
| /*****************GLUI_Master_Object::auto_set_main_gfx_viewport() **********/ |
| |
| void GLUI_Master_Object::auto_set_viewport( void ) |
| { |
| int x, y, w, h; |
| |
| get_viewport_area( &x, &y, &w, &h ); |
| glViewport( MAX(x,0), MAX(y,0), MAX(w,0), MAX(h,0) ); |
| } |
| |
| |
| |
| /***************************************** GLUI::show() **********************/ |
| |
| void GLUI::show( void ) |
| { |
| int orig_window; |
| |
| orig_window = main_panel->set_to_glut_window(); |
| |
| glutShowWindow(); |
| |
| main_panel->restore_window(orig_window); |
| } |
| |
| |
| |
| /***************************************** GLUI::hide() **********************/ |
| |
| void GLUI::hide( void ) |
| { |
| int orig_window; |
| |
| this->deactivate_current_control(); |
| |
| orig_window = main_panel->set_to_glut_window(); |
| |
| glutHideWindow(); |
| |
| main_panel->restore_window(orig_window); |
| } |
| |
| |
| /**************** GLUI_DrawingSentinal **************/ |
| GLUI_DrawingSentinal::GLUI_DrawingSentinal(GLUI_Control *c_) |
| :c(c_) |
| { |
| orig_win = c->set_to_glut_window(); |
| orig_buf = c->glui->set_current_draw_buffer(); |
| } |
| GLUI_DrawingSentinal::~GLUI_DrawingSentinal() { |
| c->glui->restore_draw_buffer(orig_buf); |
| c->restore_window(orig_win); |
| } |
| |
| |
| void GLUI_Master_Object::glui_setIdleFuncIfNecessary( void ) |
| { |
| GLUI *glui; |
| |
| glui = (GLUI*) GLUI_Master.gluis.first_child(); |
| int necessary; |
| if (this->glut_idle_CB) |
| necessary = true; |
| else { |
| necessary = false; |
| while( glui ) { |
| if( glui->needs_idle() ) { |
| necessary = true; |
| break; |
| } |
| glui = (GLUI*) glui->next(); |
| } |
| } |
| if( necessary ) |
| glutIdleFunc( glui_idle_func ); |
| else |
| glutIdleFunc( NULL ); |
| } |