~ubuntu-branches/ubuntu/edgy/glui/edgy

« back to all changes in this revision

Viewing changes to glui_spinner.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2001-09-23 12:57:28 UTC
  • Revision ID: james.westby@ubuntu.com-20010923125728-qbts7xit2eg1ogo2
Tags: upstream-2.1.0.beta
ImportĀ upstreamĀ versionĀ 2.1.0.beta

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
  
 
3
  GLUI User Interface Toolkit
 
4
  ---------------------------
 
5
 
 
6
     glui_spinner.cpp - GLUI_Spinner class
 
7
 
 
8
 
 
9
  notes: 
 
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
 
15
 
 
16
 
 
17
          --------------------------------------------------
 
18
 
 
19
  Copyright (c) 1998 Paul Rademacher
 
20
 
 
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.
 
24
 
 
25
*****************************************************************************/
 
26
 
 
27
  
 
28
#include "glui.h"
 
29
#include "stdinc.h"
 
30
#include <math.h>
 
31
 
 
32
/*static int __debug=0;              */
 
33
 
 
34
#define  GLUI_SPINNER_GROWTH_STEPS         800
 
35
#define  GLUI_SPINNER_MIN_GROWTH_STEPS     100
 
36
#define  GLUI_SPINNER_CALLBACK_INTERVAL    1
 
37
 
 
38
 
 
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         */
 
42
 
 
43
void  spinner_edittext_callback( int id )
 
44
{
 
45
  GLUI_Spinner *spinner;
 
46
 
 
47
  putchar( '.' ); flushout;
 
48
  
 
49
  spinner = (GLUI_Spinner*) id;
 
50
 
 
51
  if ( NOT spinner )
 
52
    return;
 
53
 
 
54
  spinner->do_callbacks();
 
55
}
 
56
 
 
57
 
 
58
/****************************** GLUI_Spinner::mouse_down_handler() **********/
 
59
 
 
60
int    GLUI_Spinner::mouse_down_handler( int local_x, int local_y )
 
61
{
 
62
  this->state = find_arrow( local_x, local_y );
 
63
 
 
64
  /*  printf( "spinner: mouse down  : %d/%d   arrow:%d\n", local_x, local_y,
 
65
      find_arrow( local_x, local_y ));
 
66
      */
 
67
 
 
68
  if ( state != GLUI_SPINNER_STATE_UP AND state != GLUI_SPINNER_STATE_DOWN )
 
69
    return true;
 
70
 
 
71
  reset_growth();
 
72
  if ( can_draw() )
 
73
    draw_arrows();  
 
74
 
 
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 );
 
84
  }
 
85
  
 
86
  do_click();  
 
87
  
 
88
  return false;
 
89
}
 
90
 
 
91
 
 
92
/******************************** GLUI_Spinner::mouse_up_handler() **********/
 
93
 
 
94
int    GLUI_Spinner::mouse_up_handler( int local_x, int local_y, int inside )
 
95
{
 
96
  state = GLUI_SPINNER_STATE_NONE;
 
97
 
 
98
  /*  printf("spinner: mouse up  : %d/%d    inside: %d\n",local_x,local_y,inside);              */
 
99
 
 
100
  /*glutSetCursor( GLUT_CURSOR_INHERIT );              */
 
101
  glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
 
102
 
 
103
  draw_arrows();
 
104
 
 
105
  /*  do_callbacks(); --- stub               */
 
106
  /*  if ( callback )               */
 
107
  /*  callback( this->user_id );              */
 
108
  
 
109
  return false;
 
110
}
 
111
 
 
112
 
 
113
/***************************** GLUI_Spinner::mouse_held_down_handler() ******/
 
114
 
 
115
int    GLUI_Spinner::mouse_held_down_handler( int local_x, int local_y,
 
116
                                              int new_inside)
 
117
{
 
118
  int new_state;
 
119
 
 
120
  if ( state == GLUI_SPINNER_STATE_NONE )
 
121
    return false;
 
122
 
 
123
  /*  printf("spinner: mouse held: %d/%d    inside: %d\n",local_x,local_y,
 
124
      new_inside);
 
125
      */
 
126
 
 
127
  if ( state == GLUI_SPINNER_STATE_BOTH ) {   /* dragging? */
 
128
    do_drag( local_x, local_y );
 
129
  }
 
130
  else {                                      /* not dragging */
 
131
    new_state = find_arrow( local_x, local_y );
 
132
    
 
133
    if ( new_state == state ) {
 
134
      /** Still in same arrow **/
 
135
      do_click();
 
136
    }
 
137
    else {
 
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;
 
142
      }
 
143
      else {
 
144
        /*** Here check y of mouse position to determine whether to 
 
145
          drag ***/
 
146
 
 
147
        /* ... */
 
148
      }
 
149
    }
 
150
 
 
151
    /*** We switched to up/down dragging ***/
 
152
    if ( state == GLUI_SPINNER_STATE_BOTH ) {
 
153
      glutSetCursor( GLUT_CURSOR_UP_DOWN );
 
154
      last_x = local_x;
 
155
      last_y = local_y;
 
156
 
 
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 )
 
162
        reset_growth();
 
163
    }
 
164
 
 
165
    if ( can_draw() )
 
166
      draw_arrows();
 
167
  }
 
168
 
 
169
  return false;
 
170
}
 
171
 
 
172
 
 
173
/****************************** GLUI_Spinner::key_handler() **********/
 
174
 
 
175
int    GLUI_Spinner::key_handler( unsigned char key,int modifiers )
 
176
{
 
177
  
 
178
 
 
179
  return true;
 
180
}
 
181
 
 
182
 
 
183
/****************************** GLUI_Spinner::draw() **********/
 
184
 
 
185
void    GLUI_Spinner::draw( int x, int y )
 
186
{
 
187
  int orig;
 
188
 
 
189
  if ( NOT can_draw() )
 
190
    return;
 
191
 
 
192
  orig = set_to_glut_window();
 
193
 
 
194
  if ( enabled ) {
 
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);
 
200
    else
 
201
      glui->std_bitmaps.draw( GLUI_STDBITMAP_SPINNER_UP_OFF, 
 
202
                              w-GLUI_SPINNER_ARROW_WIDTH-1,
 
203
                              GLUI_SPINNER_ARROW_Y);
 
204
 
 
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);
 
210
    else
 
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);
 
214
  }
 
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);
 
222
  }
 
223
 
 
224
  if ( active ) {
 
225
    glColor3ub( 0, 0, 0 );
 
226
    glEnable( GL_LINE_STIPPLE );
 
227
    glLineStipple( 1, 0x5555 );
 
228
  }
 
229
  else {
 
230
    glColor3ub( glui->bkgd_color.r,glui->bkgd_color.g,glui->bkgd_color.b );
 
231
  } 
 
232
 
 
233
  glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
 
234
  glDisable( GL_CULL_FACE );
 
235
  glBegin( GL_QUADS );
 
236
  glVertex2i( w-GLUI_SPINNER_ARROW_WIDTH-2, 0 );
 
237
  glVertex2i( w, 0 );
 
238
  glVertex2i( w, h );
 
239
  glVertex2i( w-GLUI_SPINNER_ARROW_WIDTH-2, h );
 
240
  glEnd();
 
241
  glDisable( GL_LINE_STIPPLE );  
 
242
  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
 
243
 
 
244
  restore_window( orig );
 
245
}
 
246
 
 
247
 
 
248
 
 
249
 
 
250
 
 
251
/********************************* GLUI_Spinner::special_handler() **********/
 
252
 
 
253
int    GLUI_Spinner::special_handler( int key,int modifiers )
 
254
{
 
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 );
 
260
  }
 
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,
 
266
                      true );
 
267
  }
 
268
  else if ( key == GLUT_KEY_HOME ) {  /** Set value to limit top - 
 
269
                                        or increment by 10 **/
 
270
  }
 
271
  else if ( key == GLUT_KEY_END ) {  
 
272
  }
 
273
 
 
274
  return true;
 
275
}
 
276
 
 
277
 
 
278
/******************************* GLUI_Spinner::set_float_val() ************/
 
279
 
 
280
void   GLUI_Spinner::set_float_val( float new_val )
 
281
 
282
  if ( NOT edittext )
 
283
    return;
 
284
 
 
285
  edittext->set_float_val( new_val );
 
286
}
 
287
 
 
288
 
 
289
/********************************** GLUI_Spinner::set_int_val() ************/
 
290
 
 
291
void   GLUI_Spinner::set_int_val( int new_val )
 
292
{
 
293
  if ( NOT edittext )
 
294
    return;
 
295
 
 
296
  edittext->set_int_val( new_val );
 
297
}
 
298
 
 
299
 
 
300
/************************************ GLUI_Spinner::update_size() **********/
 
301
 
 
302
void   GLUI_Spinner::update_size( void )
 
303
{
 
304
  /*edittext->w = this->w - GLUI_SPINNER_ARROW_WIDTH-3;              */
 
305
  this->w = edittext->w + GLUI_SPINNER_ARROW_WIDTH + 3;
 
306
}
 
307
 
 
308
 
 
309
/************************************ GLUI_Spinner::find_arrow() ************/
 
310
 
 
311
int    GLUI_Spinner::find_arrow( int local_x, int local_y )
 
312
{
 
313
  local_x -= x_abs; 
 
314
  local_y -= y_abs;
 
315
 
 
316
  if ( local_x >= (w - GLUI_SPINNER_ARROW_WIDTH) AND
 
317
       local_x <= w ) {
 
318
 
 
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;
 
322
 
 
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;
 
326
 
 
327
  }
 
328
 
 
329
  return GLUI_SPINNER_STATE_NONE;
 
330
}
 
331
 
 
332
 
 
333
/****************************** GLUI_Spinner::draw_arrows() **********/
 
334
 
 
335
void    GLUI_Spinner::draw_arrows( void )
 
336
{
 
337
  if ( NOT can_draw() )
 
338
    return;
 
339
 
 
340
  translate_and_draw_front();
 
341
}
 
342
 
 
343
 
 
344
/***************************************** GLUI_Spinner::do_click() **********/
 
345
 
 
346
void    GLUI_Spinner::do_click( void )
 
347
{
 
348
  int    direction;
 
349
  float  incr;
 
350
  float  modifier_factor;
 
351
 
 
352
  if ( state == GLUI_SPINNER_STATE_UP )
 
353
    direction = +1;
 
354
  else if ( state == GLUI_SPINNER_STATE_DOWN )
 
355
    direction = -1;
 
356
 
 
357
  increase_growth();
 
358
 
 
359
  modifier_factor = 1.0;
 
360
  if ( glui ) {
 
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;
 
365
  }
 
366
 
 
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 ***/
 
371
  }
 
372
 
 
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 ****/
 
376
  callback_count++;
 
377
  if ( (callback_count % GLUI_SPINNER_CALLBACK_INTERVAL ) == 0 )
 
378
    do_callbacks();
 
379
}
 
380
 
 
381
 
 
382
/***************************************** GLUI_Spinner::do_drag() **********/
 
383
 
 
384
void    GLUI_Spinner::do_drag( int x, int y )
 
385
{
 
386
  int   delta_y;
 
387
  float incr, modifier_factor;
 
388
  /* int delta_x;              */
 
389
 
 
390
  modifier_factor = 1.0f;
 
391
  if ( glui ) {
 
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;
 
396
  }
 
397
 
 
398
  /*  delta_x = x - last_x;              */
 
399
  delta_y = -(y - last_y);
 
400
 
 
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 ***/
 
405
  }
 
406
 
 
407
  last_x = x;
 
408
  last_y = y;
 
409
 
 
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 ****/
 
413
 
 
414
  callback_count++;
 
415
  if ( (callback_count % GLUI_SPINNER_CALLBACK_INTERVAL ) == 0 )
 
416
    do_callbacks();
 
417
}
 
418
 
 
419
 
 
420
/***************************************** GLUI_Spinner::needs_idle() ******/
 
421
 
 
422
int     GLUI_Spinner::needs_idle( void )
 
423
{
 
424
  if  (state == GLUI_SPINNER_STATE_UP OR state == GLUI_SPINNER_STATE_DOWN ) {
 
425
    return true;
 
426
  }
 
427
  else {
 
428
    return false;
 
429
  }
 
430
}
 
431
 
 
432
/***************************************** GLUI_Spinner::idle() **********/
 
433
 
 
434
void    GLUI_Spinner::idle( void )
 
435
{
 
436
  if ( NOT needs_idle() )
 
437
    return;
 
438
  else
 
439
    do_click();
 
440
}
 
441
 
 
442
 
 
443
/************************************ GLUI_Spinner::do_callbacks() **********/
 
444
 
 
445
void    GLUI_Spinner::do_callbacks( void )
 
446
{
 
447
  /*** This is not necessary, b/c edittext automatically updates us ***/
 
448
  if ( NOT edittext )
 
449
    return;
 
450
  this->float_val = edittext->float_val;
 
451
  this->int_val   = edittext->int_val;
 
452
  /*    *******************************************/
 
453
 
 
454
  if ( NOT first_callback ) {
 
455
    if ( data_type == GLUI_SPINNER_INT AND int_val == last_int_val ) {
 
456
      return;
 
457
    }
 
458
    
 
459
    if ( data_type == GLUI_SPINNER_FLOAT AND float_val == last_float_val ) {
 
460
      return;
 
461
    }
 
462
  }
 
463
  
 
464
  this->execute_callback();
 
465
 
 
466
  last_int_val   = int_val;
 
467
  last_float_val = float_val;
 
468
  first_callback = false;
 
469
}
 
470
 
 
471
 
 
472
/********************************* GLUI_Spinner::set_float_limits() *********/
 
473
 
 
474
void GLUI_Spinner::set_float_limits( float low, float high, int limit_type )
 
475
{
 
476
  if ( NOT edittext ) 
 
477
    return;
 
478
 
 
479
  edittext->set_float_limits( low, high, limit_type );
 
480
}
 
481
 
 
482
 
 
483
/*********************************** GLUI_Spinner::set_int_limits() *********/
 
484
 
 
485
void   GLUI_Spinner::set_int_limits( int low, int high, int limit_type )
 
486
{
 
487
  if ( NOT edittext ) 
 
488
    return;
 
489
  
 
490
  edittext->set_int_limits( low, high, limit_type );
 
491
}
 
492
 
 
493
 
 
494
/*********************************** GLUI_Spinner:reset_growth() *************/
 
495
 
 
496
void    GLUI_Spinner::reset_growth( void )
 
497
{
 
498
  float lo, hi;
 
499
 
 
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 )
 
504
      growth = .4f; 
 
505
  }
 
506
  else {
 
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;
 
511
    }
 
512
    else if ( data_type == GLUI_SPINNER_INT ) {
 
513
      lo = (float) edittext->int_low;
 
514
      hi = (float) edittext->int_high;
 
515
      
 
516
      growth = (hi-lo) / GLUI_SPINNER_GROWTH_STEPS;
 
517
    }
 
518
  }
 
519
 
 
520
  if ( growth == 0.0f )
 
521
    growth = .001f;
 
522
}
 
523
 
 
524
 
 
525
/******************************* GLUI_Spinner:increase_growth() *************/
 
526
 
 
527
void    GLUI_Spinner::increase_growth( void )
 
528
{
 
529
  float hi,lo;
 
530
 
 
531
  if ( data_type == GLUI_SPINNER_FLOAT ) {
 
532
    lo = edittext->float_low;
 
533
    hi = edittext->float_high;
 
534
  }
 
535
  else if ( data_type == GLUI_SPINNER_INT ) {
 
536
    lo = (float) edittext->int_low;
 
537
    hi = (float) edittext->int_high;
 
538
  }
 
539
 
 
540
  if ( growth < (hi-lo) / GLUI_SPINNER_MIN_GROWTH_STEPS )
 
541
    growth *= growth_exp;
 
542
 
 
543
  /*  printf( "growth: %f\n", growth );              */
 
544
}
 
545
 
 
546
 
 
547
/*************************************** GLUI_Spinner:get_text() *************/
 
548
 
 
549
char    *GLUI_Spinner::get_text( void )
 
550
 
551
  if (edittext) 
 
552
    return edittext->text; 
 
553
  else 
 
554
    return ""; 
 
555
}
 
556
 
 
557
 
 
558
/********************************** GLUI_Spinner:get_float_val() *************/
 
559
 
 
560
float    GLUI_Spinner::get_float_val( void )
 
561
{
 
562
  if (edittext) 
 
563
    return edittext->float_val; 
 
564
  else 
 
565
    return 0.0f; 
 
566
}
 
567
 
 
568
 
 
569
/********************************** GLUI_Spinner:get_int_val() *************/
 
570
 
 
571
int    GLUI_Spinner::get_int_val( void )
 
572
{
 
573
  if (edittext) 
 
574
    return edittext->int_val; 
 
575
  else 
 
576
    return 0; 
 
577
}
 
578
 
 
579