Permalink
Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
1250 lines (979 sloc) 30.7 KB
/****************************************************************************
GLUI User Interface Toolkit
---------------------------
glui_control.cpp - top-level GLUI_Control class
--------------------------------------------------
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>
int _glui_draw_border_only = 0;
/********* GLUI_Control::GLUI_Control() **********/
GLUI_Control::GLUI_Control()
{
x_off = GLUI_XOFF;
y_off_top = GLUI_YOFF;
y_off_bot = GLUI_YOFF;
x_abs = GLUI_XOFF;
y_abs = GLUI_YOFF;
active = false;
enabled = true;
int_val = 0;
last_live_int = 0;
float_array_size = 0;
name = tfm::format("Control: %p", this);
float_val = 0.0;
last_live_float = 0.0;
ptr_val = NULL;
glui = NULL;
w = GLUI_DEFAULT_CONTROL_WIDTH;
h = GLUI_DEFAULT_CONTROL_HEIGHT;
font = NULL;
active_type = GLUI_CONTROL_ACTIVE_MOUSEDOWN;
alignment = GLUI_ALIGN_LEFT;
is_container = false;
can_activate = true; /* By default, you can activate a control */
spacebar_mouse_click = true; /* Does spacebar simulate a mouse click? */
live_type = GLUI_LIVE_NONE;
text = "";
last_live_text = "";
live_inited = false;
collapsible = false;
is_open = true;
hidden = false;
memset(char_widths, -1, sizeof(char_widths)); /* JVK */
int i;
for( i=0; i<GLUI_DEF_MAX_ARRAY; i++ )
float_array_val[i] = last_live_float_array[i] = 0.0;
}
/********* GLUI_Control::~GLUI_Control() **********/
GLUI_Control::~GLUI_Control()
{
GLUI_Control *item = (GLUI_Control*) this->first_child();
while (item)
{
GLUI_Control *tmp = item;
item = (GLUI_Control*) item->next();
delete tmp;
}
}
/*************************** Drawing Utility routines *********************/
/* Redraw this control. */
void GLUI_Control::redraw() {
if (glui==NULL || hidden) return;
if (glui->should_redraw_now(this))
translate_and_draw_front();
}
/** Redraw everybody in our window. */
void GLUI_Control::redraw_window() {
if (glui==NULL || hidden) return;
if ( glui->get_glut_window_id() == -1 ) return;
int orig = set_to_glut_window();
glutPostRedisplay();
restore_window(orig);
}
/* GLUI_Control::translate_and_draw_front() ********/
void GLUI_Control::translate_and_draw_front()
{
GLUI_DRAWINGSENTINAL_IDIOM
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
translate_to_origin();
draw(0,0);
glPopMatrix();
}
/********** GLUI_Control::set_to_bkgd_color() ********/
void GLUI_Control::set_to_bkgd_color()
{
if ( NOT glui )
return;
glColor3ubv( glui->bkgd_color );
}
/******** GLUI_Control::draw_box_inwards_outline() ********/
void GLUI_Control::draw_box_inwards_outline( int x_min, int x_max, int y_min, int y_max )
{
glBegin( GL_LINES );
glColor3f( .5, .5, .5 );
glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
glVertex2i( x_min, y_min ); glVertex2i( x_min, y_max );
glColor3f( 1., 1., 1. );
glVertex2i( x_min, y_max ); glVertex2i( x_max, y_max );
glVertex2i( x_max, y_max ); glVertex2i( x_max, y_min );
if ( enabled )
glColor3f( 0., 0., 0. );
else
glColor3f( .25, .25, .25 );
glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 );
glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_min+1, y_max-1 );
glColor3f( .75, .75, .75 );
glVertex2i( x_min+1, y_max-1 ); glVertex2i( x_max-1, y_max-1 );
glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_max-1, y_min+1 );
glEnd();
}
/******* GLUI_Control::draw_box() **********/
void GLUI_Control::draw_box( int x_min, int x_max, int y_min, int y_max, float r, float g, float b)
{
if ( r == 1.0 AND g == 1.0 AND b == 1.0 AND NOT enabled AND glui ) {
draw_bkgd_box( x_min, x_max, y_min, y_max );
return;
}
glColor3f( r, g, b );
glBegin( GL_QUADS );
glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max );
glEnd();
}
/******* GLUI_Control::draw_bkgd_box() **********/
void GLUI_Control::draw_bkgd_box( int x_min, int x_max, int y_min, int y_max )
{
set_to_bkgd_color();
glBegin( GL_QUADS );
glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max );
glEnd();
}
/**** GLUI_Control::draw_active_area() ********/
void GLUI_Control::draw_active_box( int x_min, int x_max, int y_min, int y_max )
{
GLUI_DRAWINGSENTINAL_IDIOM
if ( active ) {
glEnable( GL_LINE_STIPPLE );
glLineStipple( 1, 0x5555 );
glColor3f( 0., 0., 0. );
} else {
set_to_bkgd_color();
}
glBegin( GL_LINE_LOOP );
glVertex2i(x_min, y_min); glVertex2i( x_max, y_min );
glVertex2i(x_max, y_max); glVertex2i( x_min, y_max );
glEnd();
glDisable( GL_LINE_STIPPLE );
}
/**** GLUI_Control::draw_emboss_box() ********/
void GLUI_Control::draw_emboss_box(int x_min,int x_max,int y_min,int y_max)
{
glLineWidth( 1.0 );
glColor3f( 1.0, 1.0, 1.0 );
glBegin( GL_LINE_LOOP );
glVertex2i( x_min, y_min ); glVertex2i( x_max, y_min );
glVertex2i( x_max, y_max ); glVertex2i( x_min, y_max );
glEnd();
glBegin( GL_LINE_LOOP );
glVertex2i( x_min+1, y_min+1 ); glVertex2i( x_max-1, y_min+1 );
glVertex2i( x_max-1, y_max-1 ); glVertex2i( x_min+1, y_max-1 );
glEnd();
glColor3f( .5, .5, .5 );
glBegin( GL_LINE_LOOP );
glVertex2i( x_min, y_min );
glVertex2i( x_max-1, y_min );
glVertex2i( x_max-1, y_max-1 );
glVertex2i( x_min, y_max-1 );
glEnd();
}
/******* GLUT_Control::draw_recursive() **********/
void GLUI_Control::draw_recursive( int x, int y )
{
GLUI_Control *node;
/* printf( "%s %d\n", this->name.c_str(), this->hidden );*/
if ( NOT can_draw() )
return;
/*if ( 1 ) { -- Debugging to check control width
glColor3f( 1.0, 0.0, 0.0 );
glBegin( GL_LINES );
glVertex2i( x_abs, y_abs );00
glVertex2i( x_abs+w, y_abs );
glEnd();
}*/
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glTranslatef( (float) this->x_abs + .5,
(float) this->y_abs + .5,
0.0 );
if ( NOT _glui_draw_border_only ) {
if ( NOT strcmp( name.c_str(), "Rollout" ) ) {
}
this->draw( this->x_off, this->y_off_top );
}
else
{
if ( dynamic_cast<GLUI_Column*>(this) ) {
/* printf( "%s w/h: %d/%d\n", (char*) name, w, h ); */
/*w = 2; */
}
/* The following draws the area of each control */
glColor3f( 1.0, 0.0, 0.0 );
glBegin( GL_LINE_LOOP );
glVertex2i( 0, 0 ); glVertex2i( w, 0 );
glVertex2i( w, h ); glVertex2i( 0, h );
glEnd();
}
glPopMatrix();
node = (GLUI_Control*) first_child();
while( node ) {
node->draw_recursive( node->x_abs, node->y_abs );
node = (GLUI_Control*) node->next();
}
}
/****** GLUI_Control::set_to_glut_window() *********/
/* Sets the current window to the glut window associated with this control */
int GLUI_Control::set_to_glut_window()
{
int orig_window;
if ( NOT glui)
return 1;
orig_window = glutGetWindow();
glutSetWindow( glui->get_glut_window_id());
return orig_window;
}
/********** GLUI_Control::restore_window() *********/
void GLUI_Control::restore_window(int orig)
{
if ( orig > 0 )
glutSetWindow( orig );
}
/****************************** Text ***************************/
/*************** GLUI_Control::set_font() **********/
void GLUI_Control::set_font(void *new_font)
{
font = new_font;
redraw();
}
/********** GLUI_Control::draw_string() ************/
void GLUI_Control::draw_string( const GLUI_String &text )
{
_glutBitmapString( get_font(), text );
}
/**************** GLUI_Control::draw_char() ********/
void GLUI_Control::draw_char(char c)
{
glutBitmapCharacter( get_font(), c );
}
/*********** GLUI_Control::string_width() **********/
int GLUI_Control::string_width(const GLUI_String &text)
{
return _glutBitmapWidthString( get_font(), text );
}
/************* GLUI_Control::char_width() **********/
int GLUI_Control::char_width(char c)
{ /* Hash table for faster character width lookups - JVK
Speeds up the textbox a little bit.
*/
int hash_index = c % CHAR_WIDTH_HASH_SIZE;
if (char_widths[hash_index][0] != c) {
char_widths[hash_index][0] = c;
char_widths[hash_index][1] = glutBitmapWidth( get_font(), c );
}
return char_widths[hash_index][1];
}
/*************** GLUI_Control::get_font() **********/
void *GLUI_Control::get_font()
{
/*** Does this control have its own font? ***/
if ( this->font != NULL )
return this->font;
/*** Does the parent glui have a font? ***/
if ( glui )
return glui->font;
/*** Return the default font ***/
return GLUT_BITMAP_HELVETICA_12;
}
/************* GLUI_Control::draw_name() ***********/
/* This draws the name of the control as either black (if enabled), or */
/* embossed if disabled. */
void GLUI_Control::draw_name(int x, int y)
{
if ( NOT can_draw() )
return;
if ( enabled )
{
set_to_bkgd_color();
glRasterPos2i(x+1, y+1);
draw_string(name);
glColor3b( 0, 0, 0 );
glRasterPos2i(x, y);
draw_string(name);
}
else
{ /* Control is disabled - emboss the string */
glColor3f( 1.0f, 1.0f, 1.0f );
glRasterPos2i(x+1, y+1);
draw_string(name);
glColor3f( .4f, .4f, .4f );
glRasterPos2i(x, y);
draw_string(name);
}
}
/**************************** Layout and Packing *********************/
/****** GLUI_Control::align() **************/
void GLUI_Control::align()
{
int col_x, col_y, col_w, col_h, col_x_off, col_y_off;
int orig_x_abs;
orig_x_abs = x_abs;
/* Fix alignment bug relating to columns */
/*return; */
if ( NOT parent() )
return; /* Clearly this shouldn't happen, though */
get_this_column_dims(&col_x, &col_y, &col_w, &col_h,
&col_x_off, &col_y_off);
if ( dynamic_cast<GLUI_Column*>(this) ) {
/* if ( this->prev() != NULL ) {
((GLUI_Control*)prev())->get_this_column_dims(&col_x, &col_y, &col_w, &col_h,
&col_x_off, &col_y_off);
x_abs = col_x + col_w;
}
else {
x_abs = ((GLUI_Control*)parent())->x_abs;
}
*/
return;
}
if ( alignment == GLUI_ALIGN_LEFT ) {
x_abs = col_x + col_x_off;
}
else if ( alignment == GLUI_ALIGN_RIGHT ) {
x_abs = col_x + col_w - col_x_off - this->w;
}
else if ( alignment == GLUI_ALIGN_CENTER ) {
x_abs = col_x + (col_w - this->w) / 2;
}
if ( this->is_container ) {
/*** Shift all child columns ***/
int delta = x_abs - orig_x_abs;
GLUI_Control *node;
node = (GLUI_Control*) this->first_child();
while( node != NULL ) {
if ( dynamic_cast<GLUI_Column*>(node) ) {
node->x_abs += delta;
}
node = (GLUI_Control*) node->next();
}
}
}
/************** GLUI_Control::pack() ************/
/* Recalculate positions and offsets */
void GLUI_Control::pack_old(int x, int y)
{
GLUI_Control *node;
int max_w, curr_y, curr_x, max_y;
int x_in = x, y_in =y;
int x_margin, y_margin_top, y_margin_bot;
int y_top_column;
int column_x;
GLUI_Column *curr_column = NULL;
this->update_size();
x_margin = this->x_off;
y_margin_top = this->y_off_top;
y_margin_bot = this->y_off_bot;
this->x_abs = x_in;
this->y_abs = y_in;
max_w = -1;
max_y = -1;
curr_x = this->x_abs + x_margin;
curr_y = this->y_abs + y_margin_top;
/*** Record start of this set of columns ***/
y_top_column = curr_y;
column_x = 0;
if ( this == glui->main_panel ) {
x=x;
}
/*** Iterate over children, packing them first ***/
node = (GLUI_Control*) this->first_child();
while( node != NULL ) {
if ( dynamic_cast<GLUI_Panel*>(node) && !node->collapsible) {
/* Pad some space above fixed size panels */
curr_y += GLUI_ITEMSPACING;
}
else if ( dynamic_cast<GLUI_Column*>(node)) {
curr_column = (GLUI_Column*) node;
if ( 1 ) {
column_x += max_w + 2 * x_margin;
curr_x += max_w + 2 * x_margin;
}
else {
column_x += max_w + 0 * x_margin;
curr_x += max_w + 0 * x_margin;
}
/*node->pack( curr_x, curr_y ); */
node->x_abs = curr_x;
node->y_abs = y_top_column;
node->w = 2;
node->h = curr_y - y_top_column;
curr_x += x_margin * 3 + 40;
curr_y = y_top_column;
max_w = 0;
node = (GLUI_Control*) node->next();
continue;
}
node->pack( curr_x, curr_y );
if ( dynamic_cast<GLUI_Panel*>(node) && !node->collapsible)
/* Pad some space below fixed size panels */
curr_y += GLUI_ITEMSPACING;
curr_y += node->h;
if ( node->w > max_w ) {
max_w = node->w;
if ( curr_column != NULL )
curr_column->w = max_w;
}
node = (GLUI_Control*) node->next();
if ( node ) {
curr_y += GLUI_ITEMSPACING;
}
if ( curr_y > max_y )
max_y = curr_y;
}
if ( this->is_container ) {
max_y += y_margin_bot; /*** Add bottom border inside box */
if ( this->first_child() ) {
if ( dynamic_cast<GLUI_Rollout*>(this) ) {
/** We don't want the rollout to shrink in width when it's
closed **/
this->w = std::max(this->w, column_x + max_w + 2 * x_margin );
}
else {
this->w = column_x + max_w + 2 * x_margin;
}
this->h = (max_y - y_in);
}
else { /* An empty container, so just assign default w & h */
this->w = GLUI_DEFAULT_CONTROL_WIDTH;
this->h = GLUI_DEFAULT_CONTROL_HEIGHT;
}
/** Expand panel if necessary (e.g., to include all the text in
a panel label) **/
this->update_size();
}
}
/*** GLUI_Control::get_this_column_dims() **********/
/* Gets the x,y,w,h,and x/y offsets of the column to which a control belongs */
void GLUI_Control::get_this_column_dims( int *col_x, int *col_y,
int *col_w, int *col_h,
int *col_x_off, int *col_y_off )
{
GLUI_Control *node, *parent_ptr;
int parent_h, parent_y_abs;
parent_ptr = (GLUI_Control*) parent();
if ( parent_ptr==NULL )
return;
parent_h = parent_ptr->h;
parent_y_abs = parent_ptr->y_abs;
if ( dynamic_cast<GLUI_Panel*>(parent_ptr) AND
parent_ptr->int_val == GLUI_PANEL_EMBOSSED AND
parent_ptr->name != "" ) {
parent_h -= GLUI_PANEL_EMBOSS_TOP;
parent_y_abs += GLUI_PANEL_EMBOSS_TOP;
}
if ( 0 ) {
GLUI_Node *first, *last, *curr;
/** Look for first control in this column **/
first = this;
while (first->prev() AND !dynamic_cast<GLUI_Column*>(first->prev()) )
first = first->prev();
/** Look for last control in this column **/
last = this;
while ( last->next() AND !dynamic_cast<GLUI_Column*>(first->next()) )
last = last->next();
curr = first;
int max_w = -1;
do {
if ( ((GLUI_Control*)curr)->w > max_w )
max_w = ((GLUI_Control*)curr)->w;
if ( curr == last )
break;
curr = curr->next();
} while( curr != NULL );
*col_x = ((GLUI_Control*)first)->x_abs;
*col_y = ((GLUI_Control*)first)->y_abs;
*col_w = max_w;
if ( parent() ) {
*col_h = ((GLUI_Control*)parent())->h;
*col_x_off = ((GLUI_Control*)parent())->x_off;
}
else {
*col_h = 10;
*col_x_off = 0;
}
*col_y_off = 0;
return;
}
if ( 1 ) { /* IS THIS WRONG? */
/*** Look for preceding column ***/
node = (GLUI_Control*) this->prev();
while( node ) {
if ( dynamic_cast<GLUI_Column*>(node) ) {
*col_x = node->x_abs;
*col_y = parent_y_abs;
*col_w = node->w;
*col_h = parent_h;
*col_x_off = node->x_off;
*col_y_off = 0;
return;
}
node = (GLUI_Control*) node->prev();
}
/*** Nope, Look for next column ***/
node = (GLUI_Control*) this->next();
while( node ) {
if ( dynamic_cast<GLUI_Column*>(node) ) {
*col_x = parent_ptr->x_abs;
*col_y = parent_y_abs;
*col_w = node->x_abs - parent_ptr->x_abs;
*col_h = parent_h;
*col_x_off = node->x_off;
*col_y_off = 0;
return;
}
node = (GLUI_Control*) node->next();
}
/*** This is single-column panel, so return panel dims ***/
*col_x = parent_ptr->x_abs;
*col_y = parent_y_abs;
*col_w = parent_ptr->w;
*col_h = parent_h;
*col_x_off = parent_ptr->x_off;
*col_y_off = 0;
}
}
void GLUI_Control::pack( int x, int y )
{
GLUI_Control *node;
int max_w, curr_y, curr_x, max_y;
int x_in = x, y_in =y;
int x_margin, y_margin_top, y_margin_bot;
int y_top_column;
int column_x;
GLUI_Column *curr_column = NULL;
this->update_size();
x_margin = this->x_off;
y_margin_top = this->y_off_top;
y_margin_bot = this->y_off_bot;
this->x_abs = x_in;
this->y_abs = y_in;
max_w = 0;
max_y = 0;
curr_x = this->x_abs + x_margin;
curr_y = this->y_abs + y_margin_top;
/*** Record start of this set of columns ***/
y_top_column = curr_y;
column_x = curr_x;
/*** Iterate over children, packing them first ***/
node = (GLUI_Control*) this->first_child();
while( node != NULL ) {
if ( dynamic_cast<GLUI_Panel*>(node) && !node->collapsible) {
/* Pad some space above fixed-size panels */
curr_y += GLUI_ITEMSPACING;
}
else if ( dynamic_cast<GLUI_Column*>(node) ) {
curr_column = (GLUI_Column*) node;
curr_x += max_w + 1 * x_margin;
column_x = curr_x;
node->x_abs = curr_x;
node->y_abs = y_top_column;
node->w = 2;
node->h = curr_y - y_top_column;
curr_x += x_margin * 1;
curr_y = y_top_column;
max_w = 0;
node = (GLUI_Control*) node->next();
continue;
}
node->pack( curr_x, curr_y );
if ( dynamic_cast<GLUI_Panel*>(node) && !node->collapsible)
/* Pad some space below fixed-size panels */
curr_y += GLUI_ITEMSPACING;
curr_y += node->h;
if ( node->w > max_w ) {
max_w = node->w;
if ( curr_column != NULL )
curr_column->w = max_w + x_margin;
}
if ( curr_y > max_y ) {
max_y = curr_y;
if ( curr_column != NULL )
curr_column->h = max_y - y_top_column;
}
node = (GLUI_Control*) node->next();
if ( node ) {
curr_y += GLUI_ITEMSPACING;
}
}
if ( this->is_container ) {
max_y += y_margin_bot; /*** Add bottom border inside box */
if ( this->first_child() ) {
this->w = column_x + max_w + 2 * x_margin - x_in;
this->h = (max_y - y_in);
}
else { /* An empty container, so just assign default w & h */
if ( !dynamic_cast<GLUI_Rollout*>(this) &&
!dynamic_cast<GLUI_Tree*>(this) ) {
this->w = GLUI_DEFAULT_CONTROL_WIDTH;
this->h = GLUI_DEFAULT_CONTROL_HEIGHT;
}
}
/** Expand panel if necessary (e.g., to include all the text in
a panel label) **/
this->update_size();
/*** Now we step through the GLUI_Columns, setting the 'h' ***/
node = (GLUI_Control*) this->first_child();
while( node != NULL ) {
if ( dynamic_cast<GLUI_Column*>(node) ) {
node->h = this->h - y_margin_bot - y_margin_top;
}
node = (GLUI_Control*) node->next();
}
}
}
/******************************** Live Variables **************************/
/*********** GLUI_Control::sync_live() ************/
/* Reads live variable and sets control to its current value */
/* This function is recursive, and operates on control's children */
void GLUI_Control::sync_live(int recurse, int draw_it)
{
GLUI_Node *node;
int sync_it=true;
int i;
float *fp;
bool changed = false;
/*** If this is currently active control, and mouse button is down,
don't sync ***/
if ( glui )
{
if ( this == glui->active_control AND glui->mouse_button_down )
sync_it = false;
/*** Actually, just disable syncing if button is down ***/
/*** Nope, go ahead and sync if mouse is down - this allows syncing in
callbacks ***/
if ( 0 ) { /* THIS CODE BELOW SHOULD NOT BE EXECUTED */
if ( glui->mouse_button_down ) {
/* printf( "Can't sync\n" ); */
return;
}
}
}
/*** If this control has a live variable, we check its current value
against the stored value in the control ***/
if ( ptr_val != NULL ) {
if ( live_type == GLUI_LIVE_NONE OR NOT sync_it ) {
}
else if ( live_type == GLUI_LIVE_INT ) {
if ( *((int*)ptr_val) != last_live_int ) {
set_int_val( *((int*)ptr_val) );
last_live_int = *((int*)ptr_val);
changed = true;
}
}
else if ( live_type == GLUI_LIVE_FLOAT ) {
if ( *((float*)ptr_val) != last_live_float ) {
set_float_val( *((float*)ptr_val) );
last_live_float = *((float*)ptr_val);
changed = true;
}
}
else if ( live_type == GLUI_LIVE_TEXT ) {
if ( last_live_text.compare((const char*)ptr_val) != 0 ) {
set_text( (char*) ptr_val );
last_live_text = (const char*)ptr_val;
changed = true;
}
}
else if ( live_type == GLUI_LIVE_STRING ) {
if ( last_live_text.compare(((std::string*) ptr_val)->c_str()) != 0 ) {
set_text( ((std::string*) ptr_val)->c_str());
last_live_text = *((std::string*) ptr_val);
changed = true;
}
}
else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
/*** Step through the arrays, and see if they're the same ***/
fp = (float*) ptr_val;
for ( i=0; i<float_array_size; i++ ) {
if ( *fp != last_live_float_array[i] ) {
changed = true;
break;
}
fp++;
}
if ( changed == true) {
fp = (float*) ptr_val;
set_float_array_val( fp );
for ( i=0; i<float_array_size; i++ ) {
last_live_float_array[i] = *fp;
fp++;
}
}
}
else if ( live_type == GLUI_LIVE_DOUBLE ) {
}
}
/*** If this control is changed and we're supposed to be drawing, then
draw it now ***/
if ( changed == true AND draw_it ) {
redraw();
}
if ( recurse ) {
/*** Now recursively output live vars for all children ***/
node = this->first_child();
while( node ) {
((GLUI_Control*) node)->sync_live(true, true);
node = node->next();
}
if ( collapsible == true AND is_open == false ) {
/** Here we have a collapsed control (e.g., a rollout that is closed **/
/** We need to go in and sync all the collapsed controls inside **/
node = this->collapsed_node.first_child();
while( node ) {
((GLUI_Control*) node)->sync_live(true, false);
node = node->next();
}
}
}
}
/********** GLUI_Control::output_live() ************/
/* Writes current value of control to live variable. */
void GLUI_Control::output_live(int update_main_gfx)
{
int i;
float *fp;
if ( ptr_val == NULL )
return;
if ( NOT live_inited )
return;
if ( live_type == GLUI_LIVE_NONE ) {
}
else if ( live_type == GLUI_LIVE_INT ) {
*((int*)ptr_val) = int_val;
last_live_int = int_val;
}
else if ( live_type == GLUI_LIVE_FLOAT ) {
*((float*)ptr_val) = float_val;
last_live_float = float_val;
}
else if ( live_type == GLUI_LIVE_TEXT ) {
strncpy( (char*) ptr_val, text.c_str(), text.length()+1);
last_live_text = text;
}
else if ( live_type == GLUI_LIVE_STRING ) {
(*(std::string*)ptr_val)= text.c_str();
last_live_text = text;
}
else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
fp = (float*) ptr_val;
for( i=0; i<float_array_size; i++ ) {
*fp = float_array_val[i];
last_live_float_array[i] = float_array_val[i];
fp++;
}
}
else if ( live_type == GLUI_LIVE_DOUBLE ) {
}
/** Update the main gfx window? **/
if ( update_main_gfx AND this->glui != NULL ) {
this->glui->post_update_main_gfx();
}
}
/****** GLUI_Control::execute_callback() **********/
void GLUI_Control::execute_callback()
{
int old_window;
old_window = glutGetWindow();
if ( glui AND glui->main_gfx_window_id != -1 )
glutSetWindow( glui->main_gfx_window_id );
this->callback( this );
// if ( this->callback )
// this->callback( this->user_id );
glutSetWindow( old_window );
}
/************** GLUI_Control::init_live() **********/
/* Reads in value of a live variable. Called once, when ctrl is created */
void GLUI_Control::init_live()
{
int i;
float *fp;
if ( ptr_val == NULL )
return;
if ( live_type == GLUI_LIVE_NONE ) {
}
else if ( live_type == GLUI_LIVE_INT ) {
set_int_val( *((int*)ptr_val) );
last_live_int = *((int*)ptr_val);
}
else if ( live_type == GLUI_LIVE_FLOAT ) {
set_float_val( *((float*)ptr_val) );
last_live_float = *((float*)ptr_val);
}
else if ( live_type == GLUI_LIVE_TEXT ) {
set_text( (const char*) ptr_val );
last_live_text = (const char*) ptr_val;
}
else if ( live_type == GLUI_LIVE_STRING ) {
set_text( ((std::string*) ptr_val)->c_str() );
last_live_text = ((std::string*) ptr_val)->c_str();
}
else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
set_float_array_val( (float*) ptr_val );
fp = (float*) ptr_val;
for( i=0; i<float_array_size; i++ ) {
last_live_float_array[i] = *fp;
fp++;
}
}
else if ( live_type == GLUI_LIVE_DOUBLE ) {
}
live_inited = true;
}
/***** GLUI_Control::set_float_array_val() ********/
void GLUI_Control::set_float_array_val( float *array_ptr )
{
int i;
if ( array_ptr == NULL )
return;
for( i=0; i<float_array_size; i++ ) {
float_array_val[i] = array_ptr[i];
}
/*** Output the live var, without updating the main gfx window ***/
output_live(false);
}
/***** GLUI_Control::get_float_array_val() ********/
void GLUI_Control::get_float_array_val( float *array_ptr )
{
int i;
if ( array_ptr == NULL )
return;
for( i=0; i<float_array_size; i++ ) {
array_ptr[i] = float_array_val[i];
}
}
/**************************** Little Utility Routines ********************/
/**** GLUI_Control::set_name() ********************/
void GLUI_Control::set_name( const GLUI_String &str )
{
name = str;
redraw();
}
/**** GLUI_Control::enable() ****************/
void GLUI_Control::enable()
{
GLUI_Control *node;
enabled = true;
if ( NOT glui )
return;
redraw();
/*** Now recursively enable all buttons below it ***/
node = (GLUI_Control*) first_child();
while(node)
{
node->enable();
node = (GLUI_Control*) node->next();
}
}
/***** GLUI_Control::disable() ****************/
void GLUI_Control::disable()
{
GLUI_Control *node;
enabled = false;
if ( NOT glui )
return;
if ( glui->active_control == this )
glui->deactivate_current_control();
redraw();
/*** Now recursively disable all buttons below it ***/
node = (GLUI_Control*) first_child();
while(node) {
node->disable();
node = (GLUI_Control*) node->next();
}
}
/******* GLUI_Control::set_w() **************/
void GLUI_Control::set_w(int new_w)
{
w = new_w;
update_size(); /* Make sure control is big enough to fit text */
if (glui) glui->refresh();
}
/**** GLUI_Control::set_h() **************/
void GLUI_Control::set_h(int new_h)
{
h = new_h;
update_size(); /* Make sure control is big enough to fit text */
if (glui) glui->refresh();
}
/***** GLUI_Control::set_alignment() ******/
void GLUI_Control::set_alignment(int new_align)
{
alignment = new_align;
if ( glui )
{
glui->align_controls(this);
redraw_window();
}
}
/***** GLUI_Control::needs_idle() *********/
/* This method gets overloaded by specific classes, e.g. Spinner. */
/* It returns whether or not a control needs to receive an idle event or not */
/* For example, a spinner only needs idle events when the user is holding */
/* the mouse down in one of the arrows. Otherwise, don't waste cycles */
/* and OpenGL context switching by calling its idle. */
bool GLUI_Control::needs_idle() const
{
return false;
}
/********* GLUI_Control::hide_internal() ********/
/** Sets hidden==true for this control and all its siblings. */
/** If recurse is true, we go to children as well */
void GLUI_Control::hide_internal( int recurse )
{
GLUI_Node *node;
node = (GLUI_Node *) this;
while( node != NULL ) {
((GLUI_Control*)node)->hidden = true;
if ( recurse AND node->first_child() != NULL )
((GLUI_Control*) node->first_child())->hide_internal(true);
node = node->next();
}
node = this->collapsed_node.first_child();
while( node != NULL ) {
((GLUI_Control*)node)->hidden = true;
if ( recurse AND node->first_child() != NULL )
((GLUI_Control*) node->first_child())->hide_internal(true);
node = node->next();
}
}
/********* GLUI_Control::unhide_internal() ********/
/** Sets hidden==false for this control and all its siblings. */
/** If recurse is true, we go to children as well */
void GLUI_Control::unhide_internal( int recurse )
{
GLUI_Node *node;
node = (GLUI_Node *) this;
while( node != NULL ) {
/* printf( "unhide: %s [%d]\n", ((GLUI_Control*)node)->name.c_str(),
((GLUI_Control*)node)->hidden );*/
((GLUI_Control*)node)->hidden = false;
if ( recurse AND node->first_child() != NULL )
((GLUI_Control*) node->first_child())->unhide_internal(true);
node = node->next();
}
node = this->collapsed_node.first_child();
while( node != NULL ) {
((GLUI_Control*)node)->hidden = false;
if ( recurse AND node->first_child() != NULL )
((GLUI_Control*) node->first_child())->unhide_internal(true);
node = node->next();
}
}