1
/****************************************************************************
3
GLUI User Interface Toolkit
4
---------------------------
6
glui_spinner.cpp - GLUI_Spinner class
10
spinner does not explicitly keep track of the current value - this is all
11
handled by the underlying edittext control
12
-> thus, spinner->sync_live() has no meaning, nor spinner->output_live
13
-> BUT, edittext will alter this spinner's float_val and int_val,
14
so that spinner->get/set will work
17
--------------------------------------------------
19
Copyright (c) 1998 Paul Rademacher
21
This program is freely distributable without licensing fees and is
22
provided without guarantee or warrantee expressed or implied. This
23
program is -not- in the public domain.
25
*****************************************************************************/
32
/*static int __debug=0; */
34
#define GLUI_SPINNER_GROWTH_STEPS 800
35
#define GLUI_SPINNER_MIN_GROWTH_STEPS 100
36
#define GLUI_SPINNER_CALLBACK_INTERVAL 1
39
/****************************** spinner_edittext_callback() ******************/
40
/* This function is not used anymore. It has been replaced by directly */
41
/* Including an optional pointer to a spinner from an edittext box */
43
void spinner_edittext_callback( int id )
45
GLUI_Spinner *spinner;
47
putchar( '.' ); flushout;
49
spinner = (GLUI_Spinner*) id;
54
spinner->do_callbacks();
58
/****************************** GLUI_Spinner::mouse_down_handler() **********/
60
int GLUI_Spinner::mouse_down_handler( int local_x, int local_y )
62
this->state = find_arrow( local_x, local_y );
64
/* printf( "spinner: mouse down : %d/%d arrow:%d\n", local_x, local_y,
65
find_arrow( local_x, local_y ));
68
if ( state != GLUI_SPINNER_STATE_UP AND state != GLUI_SPINNER_STATE_DOWN )
75
/*** ints and floats behave a bit differently. When you click on
76
an int spinner, you expect the value to immediately go up by 1, whereas
77
for a float it'll go up only by a fractional amount. Therefore, we
78
go ahead and increment by one for int spinners ***/
79
if ( data_type == GLUI_SPINNER_INT ) {
80
if ( state == GLUI_SPINNER_STATE_UP )
81
edittext->set_float_val( edittext->float_val + 1.0 );
82
else if ( state == GLUI_SPINNER_STATE_DOWN )
83
edittext->set_float_val( edittext->float_val - .9 );
92
/******************************** GLUI_Spinner::mouse_up_handler() **********/
94
int GLUI_Spinner::mouse_up_handler( int local_x, int local_y, int inside )
96
state = GLUI_SPINNER_STATE_NONE;
98
/* printf("spinner: mouse up : %d/%d inside: %d\n",local_x,local_y,inside); */
100
/*glutSetCursor( GLUT_CURSOR_INHERIT ); */
101
glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
105
/* do_callbacks(); --- stub */
106
/* if ( callback ) */
107
/* callback( this->user_id ); */
113
/***************************** GLUI_Spinner::mouse_held_down_handler() ******/
115
int GLUI_Spinner::mouse_held_down_handler( int local_x, int local_y,
120
if ( state == GLUI_SPINNER_STATE_NONE )
123
/* printf("spinner: mouse held: %d/%d inside: %d\n",local_x,local_y,
127
if ( state == GLUI_SPINNER_STATE_BOTH ) { /* dragging? */
128
do_drag( local_x, local_y );
130
else { /* not dragging */
131
new_state = find_arrow( local_x, local_y );
133
if ( new_state == state ) {
134
/** Still in same arrow **/
138
if ( new_inside OR 1) {
139
/** The state changed, but we're still inside - that
140
means we moved off the arrow: begin dragging **/
141
state = GLUI_SPINNER_STATE_BOTH;
144
/*** Here check y of mouse position to determine whether to
151
/*** We switched to up/down dragging ***/
152
if ( state == GLUI_SPINNER_STATE_BOTH ) {
153
glutSetCursor( GLUT_CURSOR_UP_DOWN );
157
/** If the spinner has limits, we reset the growth value, since
158
reset_growth() will compute a new growth value for dragging
159
vs. clicking. If the spinner has no limits, then we just let the
160
growth remain at whatever the user has incremented it up to **/
161
if ( edittext->has_limits != GLUI_LIMIT_NONE )
173
/****************************** GLUI_Spinner::key_handler() **********/
175
int GLUI_Spinner::key_handler( unsigned char key,int modifiers )
183
/****************************** GLUI_Spinner::draw() **********/
185
void GLUI_Spinner::draw( int x, int y )
189
if ( NOT can_draw() )
192
orig = set_to_glut_window();
195
/*** Draw the up arrow either pressed or unrpessed ***/
196
if ( state == GLUI_SPINNER_STATE_UP OR state == GLUI_SPINNER_STATE_BOTH )
197
glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_ON,
198
w-GLUI_SPINNER_ARROW_WIDTH-1,
199
GLUI_SPINNER_ARROW_Y);
201
glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_OFF,
202
w-GLUI_SPINNER_ARROW_WIDTH-1,
203
GLUI_SPINNER_ARROW_Y);
205
/*** Draw the down arrow either pressed or unrpessed ***/
206
if (state == GLUI_SPINNER_STATE_DOWN OR state == GLUI_SPINNER_STATE_BOTH)
207
glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_DOWN_ON,
208
w-GLUI_SPINNER_ARROW_WIDTH-1,
209
GLUI_SPINNER_ARROW_HEIGHT+GLUI_SPINNER_ARROW_Y);
211
glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_DOWN_OFF,
212
w-GLUI_SPINNER_ARROW_WIDTH-1,
213
GLUI_SPINNER_ARROW_HEIGHT+GLUI_SPINNER_ARROW_Y);
215
else { /**** The spinner is disabled ****/
216
glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_DIS,
217
w-GLUI_SPINNER_ARROW_WIDTH-1,
218
GLUI_SPINNER_ARROW_Y);
219
glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_DOWN_DIS,
220
w-GLUI_SPINNER_ARROW_WIDTH-1,
221
GLUI_SPINNER_ARROW_HEIGHT+GLUI_SPINNER_ARROW_Y);
225
glColor3ub( 0, 0, 0 );
226
glEnable( GL_LINE_STIPPLE );
227
glLineStipple( 1, 0x5555 );
230
glColor3ub( glui->bkgd_color.r,glui->bkgd_color.g,glui->bkgd_color.b );
233
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
234
glDisable( GL_CULL_FACE );
236
glVertex2i( w-GLUI_SPINNER_ARROW_WIDTH-2, 0 );
239
glVertex2i( w-GLUI_SPINNER_ARROW_WIDTH-2, h );
241
glDisable( GL_LINE_STIPPLE );
242
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
244
restore_window( orig );
251
/********************************* GLUI_Spinner::special_handler() **********/
253
int GLUI_Spinner::special_handler( int key,int modifiers )
255
if ( key == GLUT_KEY_UP ) { /** Simulate a click in the up arrow **/
256
mouse_down_handler( x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1,
257
y_abs + GLUI_SPINNER_ARROW_Y+1 );
258
mouse_up_handler( x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1,
259
y_abs + GLUI_SPINNER_ARROW_Y+1, true );
261
else if ( key == GLUT_KEY_DOWN ) { /** Simulate a click in the up arrow **/
262
mouse_down_handler(x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1,
263
y_abs+GLUI_SPINNER_ARROW_Y+1+GLUI_SPINNER_ARROW_HEIGHT);
264
mouse_up_handler( x_abs + w - GLUI_SPINNER_ARROW_WIDTH + 1,
265
y_abs+GLUI_SPINNER_ARROW_Y+1 +GLUI_SPINNER_ARROW_HEIGHT,
268
else if ( key == GLUT_KEY_HOME ) { /** Set value to limit top -
269
or increment by 10 **/
271
else if ( key == GLUT_KEY_END ) {
278
/******************************* GLUI_Spinner::set_float_val() ************/
280
void GLUI_Spinner::set_float_val( float new_val )
285
edittext->set_float_val( new_val );
289
/********************************** GLUI_Spinner::set_int_val() ************/
291
void GLUI_Spinner::set_int_val( int new_val )
296
edittext->set_int_val( new_val );
300
/************************************ GLUI_Spinner::update_size() **********/
302
void GLUI_Spinner::update_size( void )
304
/*edittext->w = this->w - GLUI_SPINNER_ARROW_WIDTH-3; */
305
this->w = edittext->w + GLUI_SPINNER_ARROW_WIDTH + 3;
309
/************************************ GLUI_Spinner::find_arrow() ************/
311
int GLUI_Spinner::find_arrow( int local_x, int local_y )
316
if ( local_x >= (w - GLUI_SPINNER_ARROW_WIDTH) AND
319
if ( local_y >= GLUI_SPINNER_ARROW_Y AND
320
local_y <= (GLUI_SPINNER_ARROW_Y+GLUI_SPINNER_ARROW_HEIGHT) )
321
return GLUI_SPINNER_STATE_UP;
323
if ( local_y >= GLUI_SPINNER_ARROW_Y+GLUI_SPINNER_ARROW_HEIGHT AND
324
local_y <= (GLUI_SPINNER_ARROW_Y+GLUI_SPINNER_ARROW_HEIGHT*2) )
325
return GLUI_SPINNER_STATE_DOWN;
329
return GLUI_SPINNER_STATE_NONE;
333
/****************************** GLUI_Spinner::draw_arrows() **********/
335
void GLUI_Spinner::draw_arrows( void )
337
if ( NOT can_draw() )
340
translate_and_draw_front();
344
/***************************************** GLUI_Spinner::do_click() **********/
346
void GLUI_Spinner::do_click( void )
350
float modifier_factor;
352
if ( state == GLUI_SPINNER_STATE_UP )
354
else if ( state == GLUI_SPINNER_STATE_DOWN )
359
modifier_factor = 1.0;
361
if ( glui->curr_modifiers & GLUT_ACTIVE_SHIFT )
362
modifier_factor = 100.0f;
363
else if ( glui->curr_modifiers & GLUT_ACTIVE_CTRL )
364
modifier_factor = .01f;
367
if ( this->data_type == GLUI_SPINNER_FLOAT OR 1) {
368
incr = growth * direction * modifier_factor * user_speed;
369
edittext->set_float_val( edittext->float_val + incr );
370
/** Remember, edittext mirrors the float and int values ***/
373
/*** Now update live variable and do callback. We don't want
374
to do the callback on each iteration of this function, just on every
375
i^th iteration, where i is given by GLUI_SPINNER_CALLBACK_INTERVAL ****/
377
if ( (callback_count % GLUI_SPINNER_CALLBACK_INTERVAL ) == 0 )
382
/***************************************** GLUI_Spinner::do_drag() **********/
384
void GLUI_Spinner::do_drag( int x, int y )
387
float incr, modifier_factor;
390
modifier_factor = 1.0f;
392
if ( glui->curr_modifiers & GLUT_ACTIVE_SHIFT )
393
modifier_factor = 100.0f;
394
else if ( glui->curr_modifiers & GLUT_ACTIVE_CTRL )
395
modifier_factor = .01f;
398
/* delta_x = x - last_x; */
399
delta_y = -(y - last_y);
401
if ( this->data_type == GLUI_SPINNER_FLOAT OR 1 ) {
402
incr = growth * delta_y * modifier_factor * user_speed;
403
edittext->set_float_val( edittext->float_val + incr );
404
/** Remember, edittext mirrors the float and int values ***/
410
/*** Now update live variable and do callback. We don't want
411
to do the callback on each iteration of this function, just on every
412
i^th iteration, where i is given by GLUI_SPINNER_CALLBACK_INTERVAL ****/
415
if ( (callback_count % GLUI_SPINNER_CALLBACK_INTERVAL ) == 0 )
420
/***************************************** GLUI_Spinner::needs_idle() ******/
422
int GLUI_Spinner::needs_idle( void )
424
if (state == GLUI_SPINNER_STATE_UP OR state == GLUI_SPINNER_STATE_DOWN ) {
432
/***************************************** GLUI_Spinner::idle() **********/
434
void GLUI_Spinner::idle( void )
436
if ( NOT needs_idle() )
443
/************************************ GLUI_Spinner::do_callbacks() **********/
445
void GLUI_Spinner::do_callbacks( void )
447
/*** This is not necessary, b/c edittext automatically updates us ***/
450
this->float_val = edittext->float_val;
451
this->int_val = edittext->int_val;
452
/* *******************************************/
454
if ( NOT first_callback ) {
455
if ( data_type == GLUI_SPINNER_INT AND int_val == last_int_val ) {
459
if ( data_type == GLUI_SPINNER_FLOAT AND float_val == last_float_val ) {
464
this->execute_callback();
466
last_int_val = int_val;
467
last_float_val = float_val;
468
first_callback = false;
472
/********************************* GLUI_Spinner::set_float_limits() *********/
474
void GLUI_Spinner::set_float_limits( float low, float high, int limit_type )
479
edittext->set_float_limits( low, high, limit_type );
483
/*********************************** GLUI_Spinner::set_int_limits() *********/
485
void GLUI_Spinner::set_int_limits( int low, int high, int limit_type )
490
edittext->set_int_limits( low, high, limit_type );
494
/*********************************** GLUI_Spinner:reset_growth() *************/
496
void GLUI_Spinner::reset_growth( void )
500
if ( edittext->has_limits == GLUI_LIMIT_NONE ) {
501
if ( data_type == GLUI_SPINNER_FLOAT )
502
growth = sqrt(ABS(edittext->float_val)) * .05f;
503
else if ( data_type == GLUI_SPINNER_INT )
507
if ( data_type == GLUI_SPINNER_FLOAT ) {
508
lo = edittext->float_low;
509
hi = edittext->float_high;
510
growth = (hi-lo) / GLUI_SPINNER_GROWTH_STEPS;
512
else if ( data_type == GLUI_SPINNER_INT ) {
513
lo = (float) edittext->int_low;
514
hi = (float) edittext->int_high;
516
growth = (hi-lo) / GLUI_SPINNER_GROWTH_STEPS;
520
if ( growth == 0.0f )
525
/******************************* GLUI_Spinner:increase_growth() *************/
527
void GLUI_Spinner::increase_growth( void )
531
if ( data_type == GLUI_SPINNER_FLOAT ) {
532
lo = edittext->float_low;
533
hi = edittext->float_high;
535
else if ( data_type == GLUI_SPINNER_INT ) {
536
lo = (float) edittext->int_low;
537
hi = (float) edittext->int_high;
540
if ( growth < (hi-lo) / GLUI_SPINNER_MIN_GROWTH_STEPS )
541
growth *= growth_exp;
543
/* printf( "growth: %f\n", growth ); */
547
/*************************************** GLUI_Spinner:get_text() *************/
549
char *GLUI_Spinner::get_text( void )
552
return edittext->text;
558
/********************************** GLUI_Spinner:get_float_val() *************/
560
float GLUI_Spinner::get_float_val( void )
563
return edittext->float_val;
569
/********************************** GLUI_Spinner:get_int_val() *************/
571
int GLUI_Spinner::get_int_val( void )
574
return edittext->int_val;