/**************************************************************************** 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(); } } } /************************************************ 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 ); } } /****************************** 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 ( !dynamic_cast(node) 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 ( dynamic_cast(node) ) { 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_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_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 ); }