Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
2106 lines (1571 sloc) 56.6 KB
/****************************************************************************
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<GLUI_Column*>(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<GLUI_EditText*>(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 );
}