1977 lines
51 KiB
C++
1977 lines
51 KiB
C++
/****************************************************************************
|
|
|
|
GLUI User Interface Toolkit
|
|
---------------------------
|
|
|
|
glui.cpp
|
|
|
|
|
|
--------------------------------------------------
|
|
|
|
Copyright (c) 1998 Paul Rademacher
|
|
|
|
This program is freely distributable without licensing fees and is
|
|
provided without guarantee or warrantee expressed or implied. This
|
|
program is -not- in the public domain.
|
|
|
|
*****************************************************************************/
|
|
|
|
#include "glui.h"
|
|
#include "stdinc.h"
|
|
|
|
|
|
void (*show_glut_keyboard_CB)(unsigned char, int, int);
|
|
void (*show_glut_special_CB)(int, int, int);
|
|
|
|
|
|
/*** This object must be used to create a GLUI ***/
|
|
|
|
GLUI_Master_Object GLUI_Master;
|
|
|
|
|
|
/************************************ finish_drawing() ************/
|
|
|
|
void finish_drawing( void )
|
|
{
|
|
glFlush();
|
|
glFinish();
|
|
}
|
|
|
|
/************************************************ GLUI::GLUI() **********/
|
|
|
|
int GLUI::init( char *text, long flags, int x, int y, int parent_window )
|
|
{
|
|
int old_glut_window;
|
|
|
|
this->flags = flags;
|
|
|
|
strncpy( window_name.string, text, sizeof(GLUI_String));
|
|
|
|
/*** 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 ) {
|
|
old_glut_window = glutGetWindow();
|
|
|
|
create_standalone_window( window_name, x, y );
|
|
setup_default_glut_callbacks();
|
|
|
|
if ( old_glut_window > 0 )
|
|
glutSetWindow( old_glut_window );
|
|
|
|
top_level_glut_window_id = glut_window_id;
|
|
}
|
|
else {
|
|
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( char *name, int x, int y )
|
|
{
|
|
glutInitWindowSize( 100, 100 );
|
|
if ( x >= 0 OR y >= 0 )
|
|
glutInitWindowPosition( x, y );
|
|
glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE ); /* | GLUT_DOUBLE ); */
|
|
glut_window_id = glutCreateWindow( name );
|
|
glDisable( GL_DEPTH_TEST );
|
|
glCullFace( GL_BACK );
|
|
glDisable( GL_CULL_FACE );
|
|
glDisable( GL_LIGHTING );
|
|
glDrawBuffer( GL_FRONT );
|
|
}
|
|
|
|
|
|
/******************************** 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 );
|
|
glDisable( GL_DEPTH_TEST );
|
|
glCullFace( GL_BACK );
|
|
glDisable( GL_CULL_FACE );
|
|
glDisable( GL_LIGHTING );
|
|
glDrawBuffer( GL_FRONT );
|
|
|
|
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 ); */
|
|
}
|
|
|
|
|
|
/********************************************** 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 ) {
|
|
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 );
|
|
|
|
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 {
|
|
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();
|
|
}
|
|
}
|
|
|
|
show_glut_keyboard_CB(key, x, y);
|
|
}
|
|
|
|
|
|
/************************************************ 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 {
|
|
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();
|
|
}
|
|
}
|
|
show_glut_special_CB(key, x, y);
|
|
}
|
|
|
|
|
|
|
|
/********************************************** 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->disactivate_current_control();
|
|
|
|
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::create_glui() ******/
|
|
|
|
GLUI *GLUI_Master_Object::create_glui( char *name, long flags,int x,int y )
|
|
{
|
|
GLUI *new_glui;
|
|
|
|
new_glui = new GLUI;
|
|
|
|
if ( new_glui ) {
|
|
new_glui->init( name, flags, x, y, -1 );
|
|
new_glui->link_this_to_parent_last( &this->gluis );
|
|
return new_glui;
|
|
}
|
|
else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/************************** GLUI_Master_Object::create_glui_subwindow() ******/
|
|
|
|
GLUI *GLUI_Master_Object::create_glui_subwindow( int parent_window,
|
|
long flags )
|
|
{
|
|
GLUI *new_glui;
|
|
char new_name[80];
|
|
|
|
new_glui = new GLUI;
|
|
|
|
if ( new_glui ) {
|
|
sprintf( new_name, "subwin_%p", this );
|
|
|
|
new_glui->init( new_name, 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;
|
|
}
|
|
else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/********************** 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;
|
|
|
|
/*glutSetWindow(1);///WOW WHAT A HACK */
|
|
|
|
/**** 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 == true ) {
|
|
close_internal();
|
|
return;
|
|
}
|
|
|
|
/* if ( TEST_AND( this->flags, GLUI_SUBWINDOW ))
|
|
check_subwindow_position();
|
|
*/
|
|
|
|
/******* 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 ); */
|
|
|
|
/* glutSwapBuffers(); //performs flush also // %%%%%%%%%% */
|
|
/* return; */
|
|
|
|
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;
|
|
}
|
|
|
|
set_ortho_projection();
|
|
|
|
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 );
|
|
|
|
/* glDrawBuffer( GL_BACK ); // Is there ever a need to draw to back buffer?? */
|
|
|
|
// main_panel->draw_bkgd_box( 0, 0, win_w, win_h );
|
|
main_panel->draw_recursive( 0, 0 );
|
|
|
|
/*glutSwapBuffers(); //performs flush also */
|
|
finish_drawing();
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************************************** _glutBitmapWidthString() **********/
|
|
|
|
int _glutBitmapWidthString( void *font, char *s )
|
|
{
|
|
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 == false ) {
|
|
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 );
|
|
*/
|
|
|
|
disactivate_current_control();
|
|
activate_control( new_control, GLUI_ACTIVATE_TAB );
|
|
}
|
|
else if ( key == ' ' AND active_control
|
|
AND active_control->spacebar_mouse_click == true ) {
|
|
/*** 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_Master_Object::set_glutMouseFunc() **********/
|
|
|
|
void GLUI_Main::set_glutMouseFunc(void (*f)(int button, int state,
|
|
int x, int y))
|
|
{
|
|
glut_mouse_CB = f;
|
|
// glutMouseFunc( glui_mouse_func );
|
|
// add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_MOUSE, (void*) f);
|
|
}
|
|
|
|
/****************************** 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.string ); */
|
|
|
|
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 disactivated when the
|
|
mouse button is released ****/
|
|
disactivate_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 - disactivate it ***/
|
|
disactivate_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 );
|
|
**/
|
|
if ( 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();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************* GLUI_Main::find_control() ******/
|
|
|
|
GLUI_Control *GLUI_Main::find_control( int x, int y )
|
|
{
|
|
GLUI_Control *node, *last_container;
|
|
|
|
last_container = NULL;
|
|
|
|
node = main_panel;
|
|
while( node != NULL ) {
|
|
if ( node->type != GLUI_CONTROL_COLUMN AND
|
|
PT_IN_BOX( x, y,
|
|
node->x_abs, node->x_abs + node->w,
|
|
node->y_abs, node->y_abs + node->h ) ) {
|
|
/*** Point is inside current node ***/
|
|
|
|
if ( node->first_child() == NULL ) {
|
|
/*** SPECIAL CASE: for edittext boxes, we make sure click is
|
|
in box, and not on name string. This should be generalized
|
|
for all controls later... ***/
|
|
if ( node->type == GLUI_CONTROL_EDITTEXT ) {
|
|
if ( x < node->x_abs + ((GLUI_EditText*)node)->text_x_offset )
|
|
return (GLUI_Control*) node->parent();
|
|
}
|
|
|
|
return node; /* point is inside this node, and node has no children,
|
|
so return this node as the selected node */
|
|
}
|
|
else {
|
|
/*** This is a container class ***/
|
|
last_container = node;
|
|
node = (GLUI_Control*) node->first_child(); /* Descend into child */
|
|
}
|
|
|
|
}
|
|
else {
|
|
node = (GLUI_Control*) node->next();
|
|
}
|
|
}
|
|
|
|
/** No leaf-level nodes found to accept the mouse click, so
|
|
return the last container control found which DOES accept the click **/
|
|
|
|
if ( last_container ) {
|
|
/* printf( "ctrl: '%s'\n", last_container->name ); */
|
|
|
|
return last_container;
|
|
}
|
|
else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/************************************* GLUI_Main::pack_controls() ***********/
|
|
|
|
void GLUI_Main::pack_controls( void )
|
|
{
|
|
main_panel->pack(0,0);
|
|
|
|
/**** Now align controls within their bounds ****/
|
|
align_controls( main_panel );
|
|
|
|
/*** If this is a subwindow, expand panel to fit parent window ***/
|
|
if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
|
|
int parent_h, parent_w;
|
|
int orig_window;
|
|
|
|
orig_window = glutGetWindow();
|
|
glutSetWindow( this->top_level_glut_window_id );
|
|
parent_h = glutGet( GLUT_WINDOW_HEIGHT );
|
|
parent_w = glutGet( GLUT_WINDOW_WIDTH );
|
|
|
|
glutSetWindow( orig_window );
|
|
|
|
/* printf( "%d %d\n", parent_h, parent_w ); */
|
|
|
|
if ( 1 ) {
|
|
if ( TEST_AND(this->flags,GLUI_SUBWINDOW_TOP )) {
|
|
main_panel->w = MAX( main_panel->w, parent_w );
|
|
}
|
|
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
|
|
main_panel->h = MAX( main_panel->h, parent_h );
|
|
}
|
|
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) {
|
|
main_panel->w = MAX( main_panel->w, parent_w );
|
|
}
|
|
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
|
|
main_panel->h = MAX( main_panel->h, parent_h );
|
|
}
|
|
}
|
|
}
|
|
|
|
this->w = main_panel->w;
|
|
this->h = main_panel->h;
|
|
}
|
|
|
|
|
|
/************************************ GLUI_Main::align_controls() **********/
|
|
|
|
void GLUI_Main::align_controls( GLUI_Control *control )
|
|
{
|
|
GLUI_Control *child;
|
|
|
|
control->align();
|
|
|
|
child = (GLUI_Control*) control->first_child();
|
|
|
|
while( child != NULL ) {
|
|
align_controls( child );
|
|
|
|
child = (GLUI_Control*)child->next();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*********************************** GLUI::set_main_gfx_window() ************/
|
|
|
|
void GLUI::set_main_gfx_window( int window_id )
|
|
{
|
|
main_gfx_window_id = window_id;
|
|
}
|
|
|
|
|
|
/********************************* GLUI_Main::post_update_main_gfx() ********/
|
|
|
|
void GLUI_Main::post_update_main_gfx( void )
|
|
{
|
|
int old_window;
|
|
|
|
if ( main_gfx_window_id > 0 ) {
|
|
old_window = glutGetWindow();
|
|
glutSetWindow( main_gfx_window_id );
|
|
glutPostRedisplay();
|
|
if( old_window > 0 )
|
|
glutSetWindow( old_window );
|
|
}
|
|
}
|
|
|
|
|
|
/********************************* GLUI_Main::set_front_draw_buffer() ********/
|
|
|
|
int GLUI_Main::set_front_draw_buffer( void )
|
|
{
|
|
GLint state;
|
|
|
|
glGetIntegerv( GL_DRAW_BUFFER, &state );
|
|
|
|
glDrawBuffer( GL_FRONT );
|
|
|
|
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;
|
|
|
|
bkgd_color.set( 200, 200, 200 );
|
|
bkgd_color_f[0] = 200.0 / 255.0;
|
|
bkgd_color_f[1] = 200.0 / 255.0;
|
|
bkgd_color_f[2] = 200.0 / 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";
|
|
glut_mouse_CB = NULL;
|
|
}
|
|
|
|
/************************************ 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->disactivate_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->translate_and_draw_front();
|
|
/*} */
|
|
}
|
|
else {
|
|
active_control = NULL;
|
|
}
|
|
|
|
/* printf( "activate: %d\n", glutGetWindow() ); */
|
|
GLUI_Master.active_control = active_control;
|
|
GLUI_Master.active_control_glui = (GLUI*) this;
|
|
}
|
|
|
|
|
|
/************************* GLUI_Main::disactivate_current_control() **********/
|
|
|
|
void GLUI_Main::disactivate_current_control( void )
|
|
{
|
|
int orig;
|
|
|
|
if ( active_control != NULL ) {
|
|
orig = active_control->set_to_glut_window();
|
|
|
|
active_control->disactivate();
|
|
|
|
/** If this isn't a container control, then redraw it in its
|
|
disactivated 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->translate_and_draw_front();
|
|
/*} */
|
|
|
|
active_control->restore_window( orig );
|
|
|
|
active_control = NULL;
|
|
}
|
|
|
|
/* printf( "disactivate: %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;
|
|
glutIdleFunc( glui_idle_func );
|
|
}
|
|
|
|
|
|
/**************************************** GLUI::disable() ********************/
|
|
|
|
void GLUI::disable( void )
|
|
{
|
|
disactivate_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))
|
|
{
|
|
show_glut_keyboard_CB = f;
|
|
// 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))
|
|
{
|
|
show_glut_special_CB = f;
|
|
// 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 ) {
|
|
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 ) {
|
|
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,
|
|
disactivate any current control **/
|
|
if ( GLUI_Master.active_control_glui != NULL )
|
|
GLUI_Master.active_control_glui->disactivate_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());
|
|
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,
|
|
disactivate any current control **/
|
|
if ( GLUI_Master.active_control_glui != NULL )
|
|
GLUI_Master.active_control_glui->disactivate_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());
|
|
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;
|
|
int new_w, new_h;
|
|
|
|
/****** 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 ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
|
|
/*** GLUI subwindow ***/
|
|
|
|
check_subwindow_position();
|
|
|
|
if ( glut_window_id > 0 )
|
|
glutSetWindow( glut_window_id );
|
|
glutPostRedisplay();
|
|
|
|
/* printf( "top_level: %d\n", top_level_glut_window_id );*/
|
|
glutSetWindow( top_level_glut_window_id );
|
|
}
|
|
else {
|
|
/*** Standalone GLUI window ***/
|
|
|
|
if ( glut_window_id > 0 )
|
|
glutSetWindow( glut_window_id );
|
|
|
|
new_h = glutGet( GLUT_WINDOW_HEIGHT );
|
|
new_w = glutGet( GLUT_WINDOW_WIDTH );
|
|
|
|
new_h = this->h;
|
|
new_w = this->w;
|
|
|
|
glutReshapeWindow( new_w, new_h );
|
|
|
|
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.string, 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->disactivate_current_control();
|
|
|
|
orig_window = main_panel->set_to_glut_window();
|
|
|
|
glutHideWindow();
|
|
|
|
main_panel->restore_window(orig_window);
|
|
}
|