Permalink
Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
848 lines (706 sloc) 23.7 KB
/****************************************************************************
GLUI User Interface Toolkit
---------------------------
glui_scrollbar.cpp - GLUI_Scrollbar class
--------------------------------------------------
Copyright (c) 2004 John Kew, 1998 Paul Rademacher
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 <algorithm>
#include <cmath>
#include <cassert>
/*static int __debug=0; */
#define GLUI_SCROLL_GROWTH_STEPS 800
#define GLUI_SCROLL_MIN_GROWTH_STEPS 100
#define GLUI_SCROLL_CALLBACK_INTERVAL 1 /* Execute the user's callback every this many clicks */
enum {
GLUI_SCROLL_ARROW_UP,
GLUI_SCROLL_ARROW_DOWN,
GLUI_SCROLL_ARROW_LEFT,
GLUI_SCROLL_ARROW_RIGHT
};
/****************************** GLUI_Scrollbar::GLUI_Scrollbar() **********/
// Constructor, no live var
GLUI_Scrollbar::GLUI_Scrollbar( GLUI_Node *parent,
const GLUI_String &name,
int horz_vert,
int data_type,
int id, GLUI_CB callback
/*,GLUI_Control *object
,GLUI_InterObject_CB obj_cb*/
)
{
common_construct(parent, name, horz_vert, data_type, NULL, id, callback/*, object, obj_cb*/);
}
/****************************** GLUI_Scrollbar::GLUI_Scrollbar() **********/
// Constructor, int live var
GLUI_Scrollbar::GLUI_Scrollbar( GLUI_Node *parent, const GLUI_String &name,
int horz_vert,
int *live_var,
int id, GLUI_CB callback
/*,GLUI_Control *object
,GLUI_InterObject_CB obj_cb*/
)
{
common_construct(parent, name, horz_vert, GLUI_SCROLL_INT, live_var, id, callback/*, object, obj_cb*/);
}
/****************************** GLUI_Scrollbar::GLUI_Scrollbar() **********/
// Constructor, float live var
GLUI_Scrollbar::GLUI_Scrollbar( GLUI_Node *parent, const GLUI_String &name,
int horz_vert,
float *live_var,
int id, GLUI_CB callback
/*,GLUI_Control *object
,GLUI_InterObject_CB obj_cb*/
)
{
common_construct(parent, name, horz_vert, GLUI_SCROLL_FLOAT, live_var, id, callback/*, object, obj_cb*/);
}
/****************************** GLUI_Scrollbar::common_init() **********/
void GLUI_Scrollbar::common_init()
{
horizontal = true;
h = GLUI_SCROLL_ARROW_HEIGHT;
w = GLUI_TEXTBOX_WIDTH;
alignment = GLUI_ALIGN_CENTER;
x_off = 0;
y_off_top = 0;
y_off_bot = 0;
can_activate = true;
state = GLUI_SCROLL_STATE_NONE;
growth_exp = GLUI_SCROLL_DEFAULT_GROWTH_EXP;
callback_count = 0;
first_callback = true;
user_speed = 1.0;
float_min = 0.0;
float_max = 0.0;
int_min = 0;
int_max = 0;
associated_object = NULL;
last_update_time=0;
velocity_limit=50.0; /* Change value by at most 50 per second */
box_length = 0;
box_start_position = 0;
box_end_position = 0;
track_length = 0;
}
/****************************** GLUI_Scrollbar::common_construct() **********/
void GLUI_Scrollbar::common_construct(
GLUI_Node *parent,
const GLUI_String &name,
int horz_vert,
int data_type,
void *data,
int id, GLUI_CB callback
/*,GLUI_Control *object,
GLUI_InterObject_CB obj_cb*/
)
{
common_init();
// make sure limits are wide enough to hold live value
if (data_type==GLUI_SCROLL_FLOAT) {
float lo = 0.0f, hi=1.0f;
if (data) {
float d = *(float*)(data);
lo = std::min(lo, d);
hi = std::max(hi, d);
}
this->set_float_limits(lo,hi);
this->set_float_val(lo);
this->live_type = GLUI_LIVE_FLOAT;
} else {
int lo = 0, hi=100;
if (data) {
int d = *(int*)(data);
lo = std::min(lo, d);
hi = std::max(hi, d);
}
this->set_int_limits(lo,hi);
this->set_int_val(0);
this->live_type = GLUI_LIVE_INT;
}
this->data_type = data_type;
this->set_ptr_val( data );
this->set_name(name);
this->user_id = id;
this->callback = callback;
//this->associated_object = object;
//this->object_cb = obj_cb;
this->horizontal=(horz_vert==GLUI_SCROLL_HORIZONTAL);
if (this->horizontal) {
this->h = GLUI_SCROLL_ARROW_HEIGHT;
this->w = GLUI_TEXTBOX_WIDTH;
} else {
this->h = GLUI_TEXTBOX_HEIGHT;
this->w = GLUI_SCROLL_ARROW_WIDTH;
}
parent->add_control( this );
this->init_live();
}
/****************************** GLUI_Scrollbar::mouse_down_handler() **********/
int GLUI_Scrollbar::mouse_down_handler( int local_x, int local_y )
{
last_update_time=GLUI_Time()-1.0;
this->state = find_arrow( local_x, local_y );
GLUI_Master.glui_setIdleFuncIfNecessary();
/* printf( "spinner: mouse down : %d/%d arrow:%d\n", local_x, local_y,
find_arrow( local_x, local_y ));
*/
if ( state != GLUI_SCROLL_STATE_UP AND state != GLUI_SCROLL_STATE_DOWN)
return true;
reset_growth();
/*** ints and floats behave a bit differently. When you click on
an int spinner, you expect the value to immediately go up by 1, whereas
for a float it'll go up only by a fractional amount. Therefore, we
go ahead and increment by one for int spinners ***/
#if 1
if ( data_type == GLUI_SCROLL_INT ) {
// Allow for possibility of reversed limits
int lo = std::min(int_min,int_max);
int hi = std::max(int_min,int_max);
int increase = int_min < int_max ? 1 : -1;
int new_val = int_val;
if ( state == GLUI_SCROLL_STATE_UP ) {
new_val += increase;
} else if ( state == GLUI_SCROLL_STATE_DOWN ) {
new_val -= increase;
}
if (new_val >= lo && new_val <= hi && new_val!=int_val) {
set_int_val(new_val);
do_callbacks();
}
}
#endif
do_click();
redraw();
return false;
}
/******************************** GLUI_Scrollbar::mouse_up_handler() **********/
int GLUI_Scrollbar::mouse_up_handler( int local_x, int local_y, bool inside )
{
state = GLUI_SCROLL_STATE_NONE;
GLUI_Master.glui_setIdleFuncIfNecessary();
/* printf("spinner: mouse up : %d/%d inside: %d\n",local_x,local_y,inside); */
/*glutSetCursor( GLUT_CURSOR_INHERIT ); */
glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
redraw();
/* do_callbacks(); --- stub */
/* if ( callback ) */
/* callback( this->user_id ); */
return false;
}
/***************************** GLUI_Scrollbar::mouse_held_down_handler() ******/
int GLUI_Scrollbar::mouse_held_down_handler( int local_x, int local_y,
bool new_inside)
{
int new_state;
if ( state == GLUI_SCROLL_STATE_NONE )
return false;
/* printf("spinner: mouse held: %d/%d inside: %d\n",local_x,local_y,
new_inside);
*/
if ( state == GLUI_SCROLL_STATE_SCROLL) { /* dragging? */
do_drag( local_x-x_abs, local_y-y_abs );
}
else { /* not dragging */
new_state = find_arrow( local_x, local_y );
if ( new_state == state ) {
/** Still in same arrow **/
do_click();
}
}
redraw();
return false;
}
/****************************** GLUI_Scrollbar::key_handler() **********/
int GLUI_Scrollbar::key_handler( unsigned char key,int modifiers )
{
return true;
}
/****************************** GLUI_Scrollbar::draw() **********/
void GLUI_Scrollbar::draw( int x, int y )
{
GLUI_DRAWINGSENTINAL_IDIOM
if ( horizontal ) {
draw_scroll_arrow(GLUI_SCROLL_ARROW_LEFT, 0, 0);
draw_scroll_arrow(GLUI_SCROLL_ARROW_RIGHT, w-GLUI_SCROLL_ARROW_WIDTH, 0);
} else {
draw_scroll_arrow(GLUI_SCROLL_ARROW_UP, 0, 0);
draw_scroll_arrow(GLUI_SCROLL_ARROW_DOWN, 0, h-GLUI_SCROLL_ARROW_HEIGHT);
}
draw_scroll();
}
/****************************** GLUI_Scrollbar::draw_scroll_arrow() **********/
void GLUI_Scrollbar::draw_scroll_arrow(int arrowtype, int x, int y)
{
float offset=0;
float L=3.5f,HC=7.f,R=10.5f;
float T=4.5f,VC=8.f,B=11.5;
const float verts[][6]={
{ L,10.5f, R, 10.5f, HC, 6.5f }, // up arrow
{ L,6.5f, R, 6.5f, HC,10.5f }, // down arrow
{ R-2,T, R-2, B, L+1, VC }, // left arrow
{ L+2,T, L+2, B, R-1, VC } // right arrow
};
const float *tri = NULL;
switch (arrowtype)
{
case GLUI_SCROLL_ARROW_UP:
tri = verts[0];
if (state & GLUI_SCROLL_STATE_UP) offset = 1;
break;
case GLUI_SCROLL_ARROW_DOWN:
tri = verts[1];
if (state & GLUI_SCROLL_STATE_DOWN) offset = 1;
break;
case GLUI_SCROLL_ARROW_LEFT:
tri = verts[2];
if (state & GLUI_SCROLL_STATE_DOWN) offset = 1;
break;
case GLUI_SCROLL_ARROW_RIGHT:
tri = verts[3];
if (state & GLUI_SCROLL_STATE_UP) offset = 1;
break;
default:
return; /* tri is NULL */
}
glColor3ubv(glui->bkgd_color);
glRecti(x,y,x+GLUI_SCROLL_ARROW_WIDTH,y+GLUI_SCROLL_ARROW_HEIGHT);
if (!offset) {
glui->draw_raised_box(x,y+1,GLUI_SCROLL_ARROW_WIDTH-1,GLUI_SCROLL_ARROW_HEIGHT-1);
} else {
glColor3ub(128,128,128);
glBegin(GL_LINE_LOOP);
int x2=x+GLUI_SCROLL_ARROW_WIDTH, y2=y+GLUI_SCROLL_ARROW_HEIGHT;
glVertex2i(x ,y);
glVertex2i(x2,y);
glVertex2i(x2,y2);
glVertex2i(x ,y2);
glEnd();
}
GLubyte black[]={0,0,0};
GLubyte white[]={255,255,255};
GLubyte gray[]={128,128,128};
GLubyte *color=black;
if (!enabled) {
offset = 1;
color = white;
}
glTranslatef(x+offset,y+offset,0);
glColor3ubv(color);
glBegin(GL_TRIANGLES);
glVertex2fv(tri); glVertex2fv(tri+2), glVertex2fv(tri+4);
glEnd();
glTranslatef(-(x+offset),-(y+offset),0);
if (!enabled) { // once more!
glTranslatef(x,y,0);
glColor3ubv(gray);
glBegin(GL_TRIANGLES);
glVertex2fv(tri); glVertex2fv(tri+2), glVertex2fv(tri+4);
glEnd();
glTranslatef(-x,-y,0);
}
}
void GLUI_Scrollbar::draw_scroll() {
update_scroll_parameters();
// Draw track using a checkerboard background
const unsigned char scroll_bg[] = {
0xD4, 0xD0, 0xC8, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xD4, 0xD0, 0xC8
};
glColor3f( 1.0, 1.0, 1.0 );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glEnable( GL_TEXTURE_2D);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
scroll_bg);
float y0 = horizontal? 0 : GLUI_SCROLL_ARROW_HEIGHT;
float y1 = horizontal? h : h-GLUI_SCROLL_ARROW_HEIGHT;
float x0 = horizontal? GLUI_SCROLL_ARROW_WIDTH : 0;
float x1 = horizontal? w-GLUI_SCROLL_ARROW_WIDTH : w;
x0-=0.5; y0+=0.5;
x1-=0.5; y1+=0.5;
float dy = y1-y0;
float dx = x1-x0;
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(x0,y0);
glTexCoord2f(dx*0.5f,0); glVertex2f(x1,y0);
glTexCoord2f(dx*0.5f,dy*0.5f); glVertex2f(x1,y1);
glTexCoord2f(0, dy*0.5f); glVertex2f(x0,y1);
glEnd();
glDisable(GL_TEXTURE_2D);
// Draw scroll box
int box = box_start_position;
if (horizontal) {
box += GLUI_SCROLL_ARROW_WIDTH;
draw_scroll_box(box,1,box_length,h);
} else {
box += GLUI_SCROLL_ARROW_HEIGHT+1;
draw_scroll_box(0,box,w,box_length);
}
}
/****************************** GLUI_Scrollbar::draw_scroll_box() **********/
void GLUI_Scrollbar::draw_scroll_box(int x, int y, int w, int h)
{
if (!enabled) return;
glColor3ubv(glui->bkgd_color);
glRecti(x,y,x+w,y+h);
glui->draw_raised_box(x,y, w-1, h-1);
if (active) {
glEnable( GL_LINE_STIPPLE );
glLineStipple( 1, 0x5555 );
glColor3f( 0., 0., 0. );
glBegin(GL_LINE_LOOP);
int x1 = x+2, y1 = y+2, x2 = x+w-4, y2 = y+h-4;
glVertex2i(x1,y1);
glVertex2i(x2,y1);
glVertex2i(x2,y2);
glVertex2i(x1,y2);
glEnd();
glDisable( GL_LINE_STIPPLE );
}
}
/**************************** update_scroll_parameters ***********/
void GLUI_Scrollbar::update_scroll_parameters() {
track_length = horizontal?
this->w-GLUI_SCROLL_ARROW_WIDTH*2 :
this->h-GLUI_SCROLL_ARROW_HEIGHT*2;
if (data_type==GLUI_SCROLL_INT)
{
if (int_max==int_min)
box_length=track_length;
else {
const int MIN_TAB = GLUI_SCROLL_BOX_STD_HEIGHT;
//box_length = int(track_length/float(visible_range));
//if (box_length < MIN_TAB)
box_length = MIN_TAB;
}
float pixels_per_unit = (track_length-box_length)/float(int_max-int_min);
if (horizontal)
box_start_position = int((int_val-int_min)*pixels_per_unit);
else
box_start_position = int((int_max-int_val)*pixels_per_unit);
box_end_position = box_start_position+box_length;
}
else if (data_type==GLUI_SCROLL_FLOAT)
{
if (float_max==float_min)
box_length=track_length;
else {
box_length = GLUI_SCROLL_BOX_STD_HEIGHT;
}
float pixels_per_unit = (track_length-box_length)/float(float_max-float_min);
if (horizontal)
box_start_position = int((float_val-float_min)*pixels_per_unit);
else
box_start_position = int((float_max-float_val)*pixels_per_unit);
box_end_position = box_start_position+box_length;
}
}
/********************************* GLUI_Scrollbar::special_handler() **********/
int GLUI_Scrollbar::special_handler( int key,int modifiers )
{
if ( !horizontal && key == GLUT_KEY_UP ) {
mouse_down_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
y_abs + 1 );
mouse_up_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
y_abs + 1, true );
}
else if ( !horizontal && key == GLUT_KEY_DOWN ) {
mouse_down_handler(x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
y_abs+1+GLUI_SCROLL_ARROW_HEIGHT);
mouse_up_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
y_abs+1 +GLUI_SCROLL_ARROW_HEIGHT,
true );
}
if ( horizontal && key == GLUT_KEY_LEFT ) {
mouse_down_handler( x_abs + 1,y_abs + 1 );
mouse_up_handler( x_abs + 1, y_abs + 1, true );
}
else if ( horizontal && key == GLUT_KEY_RIGHT ) {
mouse_down_handler(x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
y_abs+1);
mouse_up_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
y_abs+1,
true );
}
else if ( key == GLUT_KEY_HOME ) { /** Set value to limit top -
or increment by 10 **/
}
else if ( key == GLUT_KEY_END ) {
}
return true;
}
/************************************ GLUI_Scrollbar::update_size() **********/
void GLUI_Scrollbar::update_size()
{
if (horizontal) {
h = GLUI_SCROLL_ARROW_HEIGHT;
if (associated_object) {
this->w = ((GLUI_Control *)associated_object)->w;
}
}
else {
w = GLUI_SCROLL_ARROW_WIDTH;
if (associated_object) {
this->h = ((GLUI_Control *)associated_object)->h;
}
}
}
/************************************ GLUI_Scrollbar::find_arrow() ************/
int GLUI_Scrollbar::find_arrow( int local_x, int local_y )
{
local_x = local_x-x_abs;
local_y = local_y-y_abs;
if (horizontal)
{
if ( local_y >= h-GLUI_SCROLL_ARROW_HEIGHT-3 && local_y <= h)
{
update_scroll_parameters();
if ( local_x >= 0 AND local_x <= (GLUI_SCROLL_ARROW_WIDTH+box_start_position) )
{
return GLUI_SCROLL_STATE_DOWN;
}
if ( local_x >= (GLUI_SCROLL_ARROW_WIDTH+box_end_position)
AND local_x <= (w+GLUI_SCROLL_ARROW_WIDTH) )
{
return GLUI_SCROLL_STATE_UP;
}
return GLUI_SCROLL_STATE_SCROLL;
}
}
else
{
if ( local_x >= w-GLUI_SCROLL_ARROW_WIDTH-3 && local_x <= w)
{
update_scroll_parameters();
if ( local_y >= 0 AND local_y <= (GLUI_SCROLL_ARROW_HEIGHT+box_start_position) )
{
return GLUI_SCROLL_STATE_UP;
}
if ( local_y >= (GLUI_SCROLL_ARROW_HEIGHT+box_end_position)
AND local_y <= (h+GLUI_SCROLL_ARROW_HEIGHT) )
{
return GLUI_SCROLL_STATE_DOWN;
}
return GLUI_SCROLL_STATE_SCROLL;
}
}
return GLUI_SCROLL_STATE_NONE;
}
/***************************************** GLUI_Scrollbar::do_click() **********/
void GLUI_Scrollbar::do_click()
{
int direction = 0;
if ( state == GLUI_SCROLL_STATE_UP )
direction = +1;
else if ( state == GLUI_SCROLL_STATE_DOWN )
direction = -1;
if (data_type==GLUI_SCROLL_INT&&int_min>int_max) direction*=-1;
if (data_type==GLUI_SCROLL_FLOAT&&float_min>float_max) direction*=-1;
increase_growth();
float modifier_factor = 1.0;
float incr = growth * modifier_factor * user_speed ;
double frame_time=GLUI_Time()-last_update_time;
double frame_limit=velocity_limit*frame_time;
if (incr>frame_limit) incr=frame_limit; /* don't scroll faster than limit */
last_update_time=GLUI_Time();
float new_val = float_val;
new_val += direction * incr;
if (1 || data_type==GLUI_SCROLL_FLOAT) set_float_val(new_val);
if (0 && data_type==GLUI_SCROLL_INT) set_int_val((int)new_val);
//printf("do_click: incr %f val=%f float_val=%f\n",incr,new_val,float_val);
/*** Now update live variable and do callback. We don't want
to do the callback on each iteration of this function, just on every
i^th iteration, where i is given by GLUI_SCROLL_CALLBACK_INTERVAL ****/
callback_count++;
if ( (callback_count % GLUI_SCROLL_CALLBACK_INTERVAL ) == 0 )
do_callbacks();
}
/***************************************** GLUI_Scrollbar::do_drag() **********/
void GLUI_Scrollbar::do_drag( int x, int y )
{
int direction = 0;
float incr, modifier_factor;
/* int delta_x; */
int new_int_val = int_val;
float new_float_val = float_val;
int free_len = track_length-box_length;
if (free_len == 0) return;
modifier_factor = 1.0;
if ( state == GLUI_SCROLL_STATE_SCROLL) {
update_scroll_parameters();
int hbox = box_length/2;
if (horizontal) {
int track_v = x-GLUI_SCROLL_ARROW_WIDTH;
new_int_val = int_min + (track_v-hbox)*(int_max-int_min)/free_len;
new_float_val = float_min + (track_v-hbox)*(float_max-float_min)/float(free_len);
} else {
int track_v = y-GLUI_SCROLL_ARROW_HEIGHT;
new_int_val = int_max - (track_v-hbox)*(int_max-int_min)/free_len;
new_float_val = float_max - (track_v-hbox)*(float_max-float_min)/float(free_len);
}
}
else {
if ( state == GLUI_SCROLL_STATE_UP )
direction = +1;
else if ( state == GLUI_SCROLL_STATE_DOWN )
direction = -1;
incr = growth * direction * modifier_factor * user_speed;
new_int_val += direction;
new_float_val += direction * (float_max-float_min)/free_len;
}
last_y = y;
last_x = x;
/*** Now update live variable and do callback. We don't want
to do the callback on each iteration of this function, just on every
i^th iteration, where i is given by GLUI_SCROLL_CALLBACK_INTERVAL ****/
if(data_type==GLUI_SCROLL_INT)
set_int_val(new_int_val);
else if (data_type==GLUI_SCROLL_FLOAT)
set_float_val(new_float_val);
callback_count++;
if ( (callback_count % GLUI_SCROLL_CALLBACK_INTERVAL ) == 0 )
do_callbacks();
}
/***************************************** GLUI_Scrollbar::needs_idle() ******/
bool GLUI_Scrollbar::needs_idle() const
{
if (state == GLUI_SCROLL_STATE_UP OR state == GLUI_SCROLL_STATE_DOWN ) {
return true;
}
else {
return false;
}
}
/***************************************** GLUI_Scrollbar::idle() **********/
void GLUI_Scrollbar::idle()
{
if ( NOT needs_idle() )
return;
else
do_click();
}
/************************************ GLUI_Scrollbar::do_callbacks() **********/
void GLUI_Scrollbar::do_callbacks()
{
/* *******************************************/
if ( NOT first_callback ) {
if ( data_type == GLUI_SCROLL_INT AND int_val == last_int_val ) {
return;
}
if ( data_type == GLUI_SPINNER_FLOAT AND float_val == last_float_val ) {
return;
}
}
if (associated_object == NULL) {
this->execute_callback();
}
else { // Use internal Callbacks
if (object_cb) {
//object_cb(associated_object, int_val);
object_cb(this);
}
}
last_int_val = int_val;
last_float_val = float_val;
first_callback = false;
}
/********************************** GLUI_Scrollbar::set_float_val() ************/
void GLUI_Scrollbar::set_float_val( float new_val )
{
// Allow for the possibility that the limits are reversed
float hi = std::max(float_min,float_max);
float lo = std::min(float_min,float_max);
if (new_val > hi)
new_val = hi;
if (new_val < lo)
new_val = lo;
last_float_val = float_val;
float_val = new_val;
int_val = (int)new_val;
redraw();
/*** Now update the live variable ***/
output_live(true);
}
/********************************** GLUI_Scrollbar::set_int_val() ************/
void GLUI_Scrollbar::set_int_val( int new_val )
{
// Allow for the possibility that the limits are reversed
int hi = std::max(int_min,int_max);
int lo = std::min(int_min,int_max);
if (new_val > hi)
new_val = hi;
if (new_val < lo)
new_val = lo;
last_int_val = int_val;
float_val = int_val = new_val;
redraw();
/*** Now update the live variable ***/
output_live(true);
}
/*********************************** GLUI_Scrollbar::set_float_limits() *********/
void GLUI_Scrollbar::set_float_limits( float low, float high, int limit_type )
{
if (limit_type != GLUI_LIMIT_CLAMP) {
// error!
}
float_min = low;
float_max = high;
// Allow for possiblitly of reversed limits
float lo = std::min(low,high);
float hi = std::max(low,high);
if (float_val<lo) set_float_val(lo);
if (float_val>hi) set_float_val(hi);
}
/*********************************** GLUI_Scrollbar::set_int_limits() *********/
void GLUI_Scrollbar::set_int_limits( int low, int high, int limit_type )
{
if (limit_type != GLUI_LIMIT_CLAMP) {
// error!
}
int_min = low;
int_max = high;
// Allow for possiblitly of reversed limits
int lo = std::min(low,high);
int hi = std::max(low,high);
if (int_val<lo) set_int_val(lo);
if (int_val>hi) set_int_val(hi);
float_min = low;
float_max = high;
}
/*********************************** GLUI_Scrollbar::reset_growth() *************/
void GLUI_Scrollbar::reset_growth()
{
growth = fabs(float_max - float_min) / float(GLUI_SCROLL_GROWTH_STEPS);
if (data_type == GLUI_SCROLL_INT && growth<1) growth=1;
}
/******************************* GLUI_Scrollbar::increase_growth() *************/
void GLUI_Scrollbar::increase_growth()
{
float range=0;
if (data_type==GLUI_SCROLL_FLOAT)
range = fabs(float_max-float_min);
else
range = fabs(float(int_max-int_min));
if ( growth < (range / float(GLUI_SCROLL_MIN_GROWTH_STEPS)) )
growth *= growth_exp;
return;
}