Permalink
Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
2109 lines (1581 sloc) 55.5 KB
/****************************************************************************
GLUI User Interface Toolkit
---------------------------
glui.cpp
--------------------------------------------------
Copyright (c) 1998 Paul Rademacher
WWW: https://github.com/libglui/glui
Issues: https://github.com/libglui/glui/issues
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*****************************************************************************/
#include "glui_internal_control.h"
#include "tinyformat.h"
#include <algorithm>
/**
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()
{
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 GLUI_String &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 GLUI_String &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.c_str() );
}
/******************************** 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()
{
glutDisplayFunc( display_func );
glutReshapeFunc( reshape_func );
glutKeyboardFunc( keyboard_func );
glutSpecialFunc( special_func );
glutMouseFunc( mouse_func );
glutMotionFunc( motion_func );
glutPassiveMotionFunc( passive_motion_func );
glutEntryFunc( entry_func );
glutVisibilityFunc( visibility_func );
/* glutIdleFunc( idle_func ); // FIXME! 100% CPU usage! */
}
/********************************************** glui_display_func() ********/
void GLUI_Main::display_func()
{
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_Main::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_Main::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_Main::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_Main::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_Main::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_Main::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_Main::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_Main::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_Main::idle_func()
{
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 GLUI_String &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 = tfm::format("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()
{
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( bkgd_color[0] / 255.0f,
bkgd_color[1] / 255.0f,
bkgd_color[2] / 255.0f,
1.0f );
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 GLUI_String &s )
{
int width = 0;
for (auto i : s) width += glutBitmapWidth( font, i );
return width;
}
/************************************ _glutBitmapString *********************/
/* Displays the contents of a string using GLUT's bitmap character function */
/* Does not handle newlines */
void _glutBitmapString( void *font, const GLUI_String &s )
{
for (auto i : s) glutBitmapCharacter( font, i );
}
/****************************** 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()
{
/*** 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()
{
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()
{
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 = std::max( main_panel->w, parent_w );
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
main_panel->h = std::max( main_panel->h, parent_h );
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) {
main_panel->w = std::max( main_panel->w, parent_w );
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
main_panel->h = std::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()
{
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()
{
/* 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()
{
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[0] = r;
bkgd_color[1] = g;
bkgd_color[2] = b;
bkgd_color_f[0] = r / 255.0f;
bkgd_color_f[1] = g / 255.0f;
bkgd_color_f[2] = b / 255.0f;
/*** 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;
glColor3ubv( bkgd_color );
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;
glColor3ubv( bkgd_color );
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()
{
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)())
{
glut_idle_CB = f;
GLUI_Master.glui_setIdleFuncIfNecessary();
}
/**************************************** GLUI::disable() ********************/
void GLUI::disable()
{
deactivate_current_control();
main_panel->disable();
}
/******************************************** GLUI::sync_live() **************/
void GLUI::sync_live()
{
main_panel->sync_live(true, true);
}
/********************************* GLUI_Master_Object::sync_live_all() *****/
void GLUI_Master_Object::sync_live_all()
{
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()
{
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()
{
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()
{
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()
{
/*** 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()
{
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_Main::reshape_func );
add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_RESHAPE, reinterpret_cast<void(*)()>(f));
}
/**************************** GLUI_Master_Object::set_glutKeyboardFunc() ****/
void GLUI_Master_Object::set_glutKeyboardFunc(void (*f)(unsigned char key,
int x, int y))
{
glutKeyboardFunc( GLUI_Main::keyboard_func );
add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_KEYBOARD, reinterpret_cast<void(*)()>(f));
}
/*********************** GLUI_Master_Object::set_glutSpecialFunc() **********/
void GLUI_Master_Object::set_glutSpecialFunc(void (*f)(int key,
int x, int y))
{
glutSpecialFunc( GLUI_Main::special_func );
add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL, reinterpret_cast<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_Main::mouse_func );
add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_MOUSE, reinterpret_cast<void(*)()>(f));
}
void GLUI_Master_Object::set_glutDisplayFunc(void (*f)(void)) {glutDisplayFunc(f);}
void GLUI_Master_Object::set_glutTimerFunc(unsigned int millis, void (*f)(int value), int value)
{ ::glutTimerFunc(millis,f,value);}
void GLUI_Master_Object::set_glutOverlayDisplayFunc(void(*f)(void)){glutOverlayDisplayFunc(f);}
void GLUI_Master_Object::set_glutSpaceballMotionFunc(Int3_CB f) {glutSpaceballMotionFunc(f);}
void GLUI_Master_Object::set_glutSpaceballRotateFunc(Int3_CB f) {glutSpaceballRotateFunc(f);}
void GLUI_Master_Object::set_glutSpaceballButtonFunc(Int2_CB f) {glutSpaceballButtonFunc(f);}
void GLUI_Master_Object::set_glutTabletMotionFunc(Int2_CB f) {glutTabletMotionFunc(f);}
void GLUI_Master_Object::set_glutTabletButtonFunc(Int4_CB f) {glutTabletButtonFunc(f);}
void GLUI_Master_Object::set_glutMenuStatusFunc(Int3_CB f) {glutMenuStatusFunc(f);}
void GLUI_Master_Object::set_glutMenuStateFunc(Int1_CB f) {glutMenuStateFunc(f);}
void GLUI_Master_Object::set_glutButtonBoxFunc(Int2_CB f) {glutButtonBoxFunc(f);}
void GLUI_Master_Object::set_glutDialsFunc(Int2_CB f) {glutDialsFunc(f);}
/****************************** glui_parent_window_reshape_func() **********/
/* This is the reshape callback for a window that contains subwindows */
void GLUI_Main::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_Main::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_Main::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_Main::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()
{
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()
{
glViewport( 0, 0, main_panel->w, main_panel->h );
}
/****************************** GLUI_Main::refresh() ****************/
void GLUI_Main::refresh()
{
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 = std::max( 0, curr_x );
curr_y = std::max( 0, curr_y );
curr_w = std::max( 0, curr_w );
curr_h = std::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()
{
int x, y, w, h;
get_viewport_area( &x, &y, &w, &h );
glViewport( std::max(x,0), std::max(y,0), std::max(w,0), std::max(h,0) );
}
/***************************************** GLUI::show() **********************/
void GLUI::show()
{
int orig_window;
orig_window = main_panel->set_to_glut_window();
glutShowWindow();
main_panel->restore_window(orig_window);
}
/***************************************** GLUI::hide() **********************/
void GLUI::hide()
{
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()
{
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_Main::idle_func );
else
glutIdleFunc( NULL );
}