833 lines
23 KiB
C++
833 lines
23 KiB
C++
|
/****************************************************************************
|
||
|
|
||
|
GLUI User Interface Toolkit
|
||
|
---------------------------
|
||
|
|
||
|
glui_scrollbar.cpp - GLUI_Scrollbar class
|
||
|
|
||
|
--------------------------------------------------
|
||
|
|
||
|
Copyright (c) 2004 John Kew, 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_internal_control.h"
|
||
|
#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 char *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 char *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 char *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(void)
|
||
|
{
|
||
|
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 char *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 = MIN(lo, d);
|
||
|
hi = 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 = MIN(lo, d);
|
||
|
hi = 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 = MIN(int_min,int_max);
|
||
|
int hi = 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.r);
|
||
|
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.r);
|
||
|
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( void )
|
||
|
{
|
||
|
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( void )
|
||
|
{
|
||
|
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( void ) 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( void )
|
||
|
{
|
||
|
if ( NOT needs_idle() )
|
||
|
return;
|
||
|
else
|
||
|
do_click();
|
||
|
}
|
||
|
|
||
|
|
||
|
/************************************ GLUI_Scrollbar::do_callbacks() **********/
|
||
|
|
||
|
void GLUI_Scrollbar::do_callbacks( void )
|
||
|
{
|
||
|
|
||
|
/* *******************************************/
|
||
|
|
||
|
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 = MAX(float_min,float_max);
|
||
|
float lo = 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 = MAX(int_min,int_max);
|
||
|
int lo = 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 = MIN(low,high);
|
||
|
float hi = 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 = MIN(low,high);
|
||
|
int hi = 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( void )
|
||
|
{
|
||
|
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( void )
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|