glui_scrollbar.cpp
上传用户:gb3593
上传日期:2022-01-07
资源大小:3028k
文件大小:24k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /****************************************************************************
  2.   
  3.   GLUI User Interface Toolkit
  4.   ---------------------------
  5.      glui_scrollbar.cpp - GLUI_Scrollbar class
  6.           --------------------------------------------------
  7.   Copyright (c) 2004 John Kew, 1998 Paul Rademacher
  8.   This program is freely distributable without licensing fees and is
  9.   provided without guarantee or warrantee expressed or implied. This
  10.   program is -not- in the public domain.
  11. *****************************************************************************/
  12. #include "glui_internal_control.h"
  13. #include <cmath>
  14. #include <cassert>
  15. /*static int __debug=0;              */
  16. #define  GLUI_SCROLL_GROWTH_STEPS         800
  17. #define  GLUI_SCROLL_MIN_GROWTH_STEPS     100
  18. #define  GLUI_SCROLL_CALLBACK_INTERVAL    1    /* Execute the user's callback every this many clicks */
  19. enum {
  20.   GLUI_SCROLL_ARROW_UP,
  21.   GLUI_SCROLL_ARROW_DOWN,
  22.   GLUI_SCROLL_ARROW_LEFT,
  23.   GLUI_SCROLL_ARROW_RIGHT
  24. };
  25.   
  26. /****************************** GLUI_Scrollbar::GLUI_Scrollbar() **********/
  27. // Constructor, no live var
  28. GLUI_Scrollbar::GLUI_Scrollbar( GLUI_Node *parent,
  29.                                 const char *name, 
  30.                                 int horz_vert,
  31.                                 int data_type,
  32.                                 int id, GLUI_CB callback
  33.                                 /*,GLUI_Control *object
  34.                                 ,GLUI_InterObject_CB obj_cb*/
  35.                                 )
  36. {
  37.   common_construct(parent, name, horz_vert, data_type, NULL, id, callback/*, object, obj_cb*/);
  38. }
  39. /****************************** GLUI_Scrollbar::GLUI_Scrollbar() **********/
  40. // Constructor, int live var
  41. GLUI_Scrollbar::GLUI_Scrollbar( GLUI_Node *parent, const char *name, 
  42.                                 int horz_vert,
  43.                                 int *live_var,
  44.                                 int id, GLUI_CB callback
  45.                                 /*,GLUI_Control *object
  46.                                 ,GLUI_InterObject_CB obj_cb*/
  47.                                 )
  48. {
  49.   common_construct(parent, name, horz_vert, GLUI_SCROLL_INT, live_var, id, callback/*, object, obj_cb*/);
  50. }
  51. /****************************** GLUI_Scrollbar::GLUI_Scrollbar() **********/
  52. // Constructor, float live var
  53. GLUI_Scrollbar::GLUI_Scrollbar( GLUI_Node *parent, const char *name,
  54.                                 int horz_vert,
  55.                                 float *live_var,
  56.                                 int id, GLUI_CB callback
  57.                                 /*,GLUI_Control *object
  58.                                 ,GLUI_InterObject_CB obj_cb*/
  59.                                 )
  60. {
  61.   common_construct(parent, name, horz_vert, GLUI_SCROLL_FLOAT, live_var, id, callback/*, object, obj_cb*/);
  62. }
  63. /****************************** GLUI_Scrollbar::common_init() **********/
  64. void GLUI_Scrollbar::common_init(void)
  65. {
  66.    horizontal = true;
  67.    h = GLUI_SCROLL_ARROW_HEIGHT;
  68.    w = GLUI_TEXTBOX_WIDTH;
  69.    alignment = GLUI_ALIGN_CENTER;
  70.    x_off = 0;
  71.    y_off_top = 0;
  72.    y_off_bot = 0;
  73.    can_activate = true;
  74.    state = GLUI_SCROLL_STATE_NONE;
  75.    growth_exp = GLUI_SCROLL_DEFAULT_GROWTH_EXP;
  76.    callback_count = 0;
  77.    first_callback = true;
  78.    user_speed = 1.0;
  79.    float_min = 0.0;
  80.    float_max = 0.0;
  81.    int_min = 0;
  82.    int_max = 0;
  83.    associated_object = NULL;
  84.    last_update_time=0;
  85.    velocity_limit=50.0; /* Change value by at most 50 per second */
  86.    box_length       = 0;
  87.    box_start_position = 0;
  88.    box_end_position   = 0;
  89.    track_length       = 0;
  90. }
  91. /****************************** GLUI_Scrollbar::common_construct() **********/
  92. void GLUI_Scrollbar::common_construct(
  93.   GLUI_Node *parent,
  94.   const char *name, 
  95.   int horz_vert,
  96.   int data_type,
  97.   void *data,
  98.   int id, GLUI_CB callback
  99.   /*,GLUI_Control *object,
  100.   GLUI_InterObject_CB obj_cb*/
  101.   )
  102. {
  103.   common_init();
  104.   // make sure limits are wide enough to hold live value
  105.   if (data_type==GLUI_SCROLL_FLOAT) {
  106.     float lo = 0.0f, hi=1.0f;
  107.     if (data) {
  108.       float d = *(float*)(data);
  109.       lo = MIN(lo, d);
  110.       hi = MAX(hi, d);
  111.     }
  112.     this->set_float_limits(lo,hi);
  113.     this->set_float_val(lo);
  114.     this->live_type = GLUI_LIVE_FLOAT;
  115.   } else {
  116.     int lo = 0, hi=100;
  117.     if (data) {
  118.       int d = *(int*)(data);
  119.       lo = MIN(lo, d);
  120.       hi = MAX(hi, d);
  121.     }
  122.     this->set_int_limits(lo,hi);
  123.     this->set_int_val(0);
  124.     this->live_type = GLUI_LIVE_INT;
  125.   }
  126.   this->data_type = data_type;
  127.   this->set_ptr_val( data );
  128.   this->set_name(name);
  129.   this->user_id = id;
  130.   this->callback    = callback;
  131.   //this->associated_object = object;
  132.   //this->object_cb = obj_cb;
  133.   this->horizontal=(horz_vert==GLUI_SCROLL_HORIZONTAL);
  134.   if (this->horizontal) {
  135.     this->h = GLUI_SCROLL_ARROW_HEIGHT;
  136.     this->w = GLUI_TEXTBOX_WIDTH;
  137.   } else {
  138.     this->h = GLUI_TEXTBOX_HEIGHT;
  139.     this->w = GLUI_SCROLL_ARROW_WIDTH;
  140.   }
  141.   parent->add_control( this );
  142.   this->init_live();
  143. }
  144.  
  145. /****************************** GLUI_Scrollbar::mouse_down_handler() **********/
  146. int    GLUI_Scrollbar::mouse_down_handler( int local_x, int local_y )
  147. {
  148.   last_update_time=GLUI_Time()-1.0;
  149.   this->state = find_arrow( local_x, local_y );
  150.   GLUI_Master.glui_setIdleFuncIfNecessary();
  151.   /*  printf( "spinner: mouse down  : %d/%d   arrow:%dn", local_x, local_y,
  152.       find_arrow( local_x, local_y ));
  153.       */
  154.   if ( state != GLUI_SCROLL_STATE_UP AND state != GLUI_SCROLL_STATE_DOWN)
  155.     return true;
  156.   reset_growth();
  157.   /*** ints and floats behave a bit differently.  When you click on
  158.     an int spinner, you expect the value to immediately go up by 1, whereas
  159.     for a float it'll go up only by a fractional amount.  Therefore, we
  160.     go ahead and increment by one for int spinners ***/
  161. #if 1
  162.   if ( data_type == GLUI_SCROLL_INT ) {
  163.     // Allow for possibility of reversed limits
  164.     int lo = MIN(int_min,int_max);
  165.     int hi = MAX(int_min,int_max);
  166.     int increase = int_min < int_max ? 1 : -1;
  167.     int new_val = int_val;
  168.     if ( state == GLUI_SCROLL_STATE_UP ) {
  169.       new_val += increase;
  170.     } else if ( state == GLUI_SCROLL_STATE_DOWN ) {
  171.       new_val -= increase;
  172.     }
  173.     if (new_val >= lo && new_val <= hi && new_val!=int_val) {
  174.       set_int_val(new_val);
  175.       do_callbacks();
  176.     }
  177.   }
  178. #endif
  179.   do_click();  
  180.   redraw();
  181.   
  182.   return false;
  183. }
  184. /******************************** GLUI_Scrollbar::mouse_up_handler() **********/
  185. int    GLUI_Scrollbar::mouse_up_handler( int local_x, int local_y, bool inside )
  186. {
  187.   state = GLUI_SCROLL_STATE_NONE;
  188.   GLUI_Master.glui_setIdleFuncIfNecessary();
  189.   /*  printf("spinner: mouse up  : %d/%d    inside: %dn",local_x,local_y,inside);              */
  190.   /*glutSetCursor( GLUT_CURSOR_INHERIT );              */
  191.   glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
  192.   redraw();
  193.   /*  do_callbacks(); --- stub               */
  194.   /*  if ( callback )               */
  195.   /*  callback( this->user_id );              */
  196.   
  197.   return false;
  198. }
  199. /***************************** GLUI_Scrollbar::mouse_held_down_handler() ******/
  200. int    GLUI_Scrollbar::mouse_held_down_handler( int local_x, int local_y,
  201.                                                 bool new_inside)
  202. {
  203.   int new_state;
  204.   if ( state == GLUI_SCROLL_STATE_NONE )
  205.     return false;
  206.   
  207.   /*  printf("spinner: mouse held: %d/%d    inside: %dn",local_x,local_y,
  208.       new_inside);
  209.   */
  210.   if ( state == GLUI_SCROLL_STATE_SCROLL) {   /* dragging? */
  211.     do_drag( local_x-x_abs, local_y-y_abs );
  212.   }
  213.   else {                                      /* not dragging */
  214.     new_state = find_arrow( local_x, local_y );
  215.     if ( new_state == state ) {
  216.       /** Still in same arrow **/
  217.       do_click();
  218.     }
  219.   }
  220.   redraw();
  221.   return false;
  222. }
  223. /****************************** GLUI_Scrollbar::key_handler() **********/
  224. int    GLUI_Scrollbar::key_handler( unsigned char key,int modifiers )
  225. {
  226.   return true;
  227. }
  228. /****************************** GLUI_Scrollbar::draw() **********/
  229. void    GLUI_Scrollbar::draw( int x, int y )
  230. {
  231.   GLUI_DRAWINGSENTINAL_IDIOM
  232.   if ( horizontal ) {
  233.     draw_scroll_arrow(GLUI_SCROLL_ARROW_LEFT,  0, 0);
  234.     draw_scroll_arrow(GLUI_SCROLL_ARROW_RIGHT, w-GLUI_SCROLL_ARROW_WIDTH, 0);
  235.   } else {
  236.     draw_scroll_arrow(GLUI_SCROLL_ARROW_UP,  0, 0);
  237.     draw_scroll_arrow(GLUI_SCROLL_ARROW_DOWN, 0, h-GLUI_SCROLL_ARROW_HEIGHT);
  238.   }
  239.   draw_scroll();
  240. }
  241. /****************************** GLUI_Scrollbar::draw_scroll_arrow() **********/
  242. void GLUI_Scrollbar::draw_scroll_arrow(int arrowtype, int x, int y)
  243. {
  244.   float offset=0;
  245.   float L=3.5f,HC=7.f,R=10.5f;
  246.   float T=4.5f,VC=8.f,B=11.5;
  247.   const float verts[][6]={
  248.     { L,10.5f,     R, 10.5f,      HC, 6.5f }, // up arrow
  249.     { L,6.5f,      R, 6.5f,       HC,10.5f }, // down arrow
  250.     { R-2,T,       R-2, B,        L+1,  VC   }, // left arrow
  251.     { L+2,T,       L+2, B,        R-1,  VC   }  // right arrow
  252.   };
  253.   const float *tri = NULL;
  254.   switch (arrowtype)
  255.   {
  256.     case GLUI_SCROLL_ARROW_UP:
  257.       tri = verts[0];
  258.       if (state & GLUI_SCROLL_STATE_UP) offset = 1;
  259.       break;
  260.     case GLUI_SCROLL_ARROW_DOWN:
  261.       tri = verts[1];
  262.       if (state & GLUI_SCROLL_STATE_DOWN) offset = 1;
  263.       break;
  264.     case GLUI_SCROLL_ARROW_LEFT:
  265.       tri = verts[2];
  266.       if (state & GLUI_SCROLL_STATE_DOWN) offset = 1;
  267.       break;
  268.     case GLUI_SCROLL_ARROW_RIGHT:
  269.       tri = verts[3];
  270.       if (state & GLUI_SCROLL_STATE_UP) offset = 1;
  271.       break;
  272.     default:
  273.       return; /* tri is NULL */
  274.   }
  275.   glColor3ubv(&glui->bkgd_color.r);
  276.   glRecti(x,y,x+GLUI_SCROLL_ARROW_WIDTH,y+GLUI_SCROLL_ARROW_HEIGHT);
  277.   if (!offset) {
  278.     glui->draw_raised_box(x,y+1,GLUI_SCROLL_ARROW_WIDTH-1,GLUI_SCROLL_ARROW_HEIGHT-1);
  279.   } else {
  280.     glColor3ub(128,128,128);
  281.     glBegin(GL_LINE_LOOP);
  282.     int x2=x+GLUI_SCROLL_ARROW_WIDTH, y2=y+GLUI_SCROLL_ARROW_HEIGHT;
  283.     glVertex2i(x ,y); 
  284.     glVertex2i(x2,y);
  285.     glVertex2i(x2,y2); 
  286.     glVertex2i(x ,y2);
  287.     glEnd();
  288.   }
  289.   
  290.   GLubyte black[]={0,0,0};
  291.   GLubyte white[]={255,255,255};
  292.   GLubyte  gray[]={128,128,128};
  293.   GLubyte *color=black;
  294.   if (!enabled) {
  295.     offset = 1;
  296.     color = white;
  297.   }
  298.   glTranslatef(x+offset,y+offset,0);
  299.   glColor3ubv(color);
  300.   glBegin(GL_TRIANGLES);
  301.   glVertex2fv(tri); glVertex2fv(tri+2), glVertex2fv(tri+4);
  302.   glEnd();
  303.   glTranslatef(-(x+offset),-(y+offset),0);
  304.   
  305.   if (!enabled) { // once more!
  306.     glTranslatef(x,y,0);
  307.     glColor3ubv(gray);
  308.     glBegin(GL_TRIANGLES);
  309.     glVertex2fv(tri); glVertex2fv(tri+2), glVertex2fv(tri+4);
  310.     glEnd();
  311.     glTranslatef(-x,-y,0);
  312.   }
  313. }
  314. void GLUI_Scrollbar::draw_scroll() {
  315.   update_scroll_parameters();
  316.   // Draw track using a checkerboard background
  317.   const unsigned char scroll_bg[] = {
  318.     0xD4, 0xD0, 0xC8, 0xFF, 0xFF, 0xFF,
  319.     0xFF, 0xFF, 0xFF, 0xD4, 0xD0, 0xC8
  320.   };
  321.   glColor3f( 1.0, 1.0, 1.0 );
  322.   glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
  323.   glEnable( GL_TEXTURE_2D);
  324.   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  325.   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  326.   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
  327.   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  328.   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  329.   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE,
  330.      scroll_bg);
  331.   
  332.   float y0 = horizontal? 0 : GLUI_SCROLL_ARROW_HEIGHT;
  333.   float y1 = horizontal? h : h-GLUI_SCROLL_ARROW_HEIGHT;
  334.   float x0 = horizontal? GLUI_SCROLL_ARROW_WIDTH   : 0;
  335.   float x1 = horizontal? w-GLUI_SCROLL_ARROW_WIDTH : w;
  336.   x0-=0.5; y0+=0.5;
  337.   x1-=0.5; y1+=0.5;
  338.   float dy = y1-y0;
  339.   float dx = x1-x0;
  340.   glBegin(GL_QUADS);
  341.   glTexCoord2f(0,     0);        glVertex2f(x0,y0);
  342.   glTexCoord2f(dx*0.5f,0);       glVertex2f(x1,y0);
  343.   glTexCoord2f(dx*0.5f,dy*0.5f); glVertex2f(x1,y1);
  344.   glTexCoord2f(0,      dy*0.5f); glVertex2f(x0,y1);
  345.   glEnd();
  346.   glDisable(GL_TEXTURE_2D);
  347.   // Draw scroll box
  348.   int box = box_start_position;
  349.   if (horizontal) {
  350.     box += GLUI_SCROLL_ARROW_WIDTH;
  351.     draw_scroll_box(box,1,box_length,h);
  352.   } else {
  353.     box += GLUI_SCROLL_ARROW_HEIGHT+1;
  354.     draw_scroll_box(0,box,w,box_length);
  355.   }
  356. }
  357. /****************************** GLUI_Scrollbar::draw_scroll_box() **********/
  358. void GLUI_Scrollbar::draw_scroll_box(int x, int y, int w, int h)
  359. {
  360.   if (!enabled) return;
  361.   glColor3ubv(&glui->bkgd_color.r);
  362.   glRecti(x,y,x+w,y+h);
  363.   glui->draw_raised_box(x,y, w-1, h-1);
  364.   
  365.   if (active) {
  366.     glEnable( GL_LINE_STIPPLE );
  367.     glLineStipple( 1, 0x5555 );
  368.     glColor3f( 0., 0., 0. );
  369.     glBegin(GL_LINE_LOOP);
  370.     int x1 = x+2, y1 = y+2, x2 = x+w-4, y2 = y+h-4;
  371.     glVertex2i(x1,y1);
  372.     glVertex2i(x2,y1);
  373.     glVertex2i(x2,y2);
  374.     glVertex2i(x1,y2);
  375.     glEnd();
  376.     glDisable( GL_LINE_STIPPLE );
  377.   }
  378. }
  379. /**************************** update_scroll_parameters ***********/
  380. void GLUI_Scrollbar::update_scroll_parameters() {
  381.   track_length = horizontal? 
  382.     this->w-GLUI_SCROLL_ARROW_WIDTH*2 :
  383.     this->h-GLUI_SCROLL_ARROW_HEIGHT*2;
  384.   if (data_type==GLUI_SCROLL_INT) 
  385.   {
  386.     if (int_max==int_min) 
  387.       box_length=track_length;
  388.     else {
  389.       const int MIN_TAB = GLUI_SCROLL_BOX_STD_HEIGHT;
  390.       //box_length = int(track_length/float(visible_range));
  391.       //if (box_length < MIN_TAB)
  392.         box_length = MIN_TAB;
  393.     }
  394.     float pixels_per_unit = (track_length-box_length)/float(int_max-int_min);
  395.     if (horizontal)
  396.       box_start_position = int((int_val-int_min)*pixels_per_unit);
  397.     else 
  398.       box_start_position = int((int_max-int_val)*pixels_per_unit);
  399.     box_end_position = box_start_position+box_length;
  400.   }
  401.   else if (data_type==GLUI_SCROLL_FLOAT) 
  402.   {
  403.     if (float_max==float_min) 
  404.       box_length=track_length;
  405.     else {
  406.       box_length = GLUI_SCROLL_BOX_STD_HEIGHT;
  407.     }
  408.     float pixels_per_unit = (track_length-box_length)/float(float_max-float_min);
  409.     if (horizontal)
  410.       box_start_position = int((float_val-float_min)*pixels_per_unit);
  411.     else 
  412.       box_start_position = int((float_max-float_val)*pixels_per_unit);
  413.     box_end_position = box_start_position+box_length;
  414.   }
  415. }
  416. /********************************* GLUI_Scrollbar::special_handler() **********/
  417. int    GLUI_Scrollbar::special_handler( int key,int modifiers )
  418. {
  419.   if ( !horizontal && key == GLUT_KEY_UP ) {
  420.     mouse_down_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
  421.       y_abs + 1 );
  422.     mouse_up_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
  423.       y_abs + 1, true );
  424.   }
  425.   else if ( !horizontal && key == GLUT_KEY_DOWN ) {
  426.     mouse_down_handler(x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
  427.       y_abs+1+GLUI_SCROLL_ARROW_HEIGHT);
  428.     mouse_up_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
  429.       y_abs+1 +GLUI_SCROLL_ARROW_HEIGHT,
  430.       true );
  431.   }
  432.   if ( horizontal && key == GLUT_KEY_LEFT ) {
  433.     mouse_down_handler( x_abs + 1,y_abs + 1 );
  434.     mouse_up_handler( x_abs + 1,   y_abs + 1, true );
  435.   }
  436.   else if ( horizontal && key == GLUT_KEY_RIGHT ) {
  437.     mouse_down_handler(x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
  438.       y_abs+1);
  439.     mouse_up_handler( x_abs + w - GLUI_SCROLL_ARROW_WIDTH + 1,
  440.       y_abs+1,
  441.       true );
  442.   }
  443.   else if ( key == GLUT_KEY_HOME ) {  /** Set value to limit top - 
  444.                                           or increment by 10 **/
  445.   }
  446.   else if ( key == GLUT_KEY_END ) {  
  447.   }
  448.   return true;
  449. }
  450. /************************************ GLUI_Scrollbar::update_size() **********/
  451. void   GLUI_Scrollbar::update_size( void )
  452. {
  453.   if (horizontal) {
  454.     h = GLUI_SCROLL_ARROW_HEIGHT;
  455.     if (associated_object) {
  456.       this->w = ((GLUI_Control *)associated_object)->w;
  457.     }
  458.   }
  459.   else {
  460.     w = GLUI_SCROLL_ARROW_WIDTH;
  461.     if (associated_object) {
  462.       this->h = ((GLUI_Control *)associated_object)->h;
  463.     }
  464.   }
  465. }
  466.  
  467. /************************************ GLUI_Scrollbar::find_arrow() ************/
  468. int    GLUI_Scrollbar::find_arrow( int local_x, int local_y )
  469. {
  470.   local_x = local_x-x_abs; 
  471.   local_y = local_y-y_abs;
  472.   if (horizontal) 
  473.   {
  474.     if ( local_y >=  h-GLUI_SCROLL_ARROW_HEIGHT-3 && local_y <= h) 
  475.     {
  476.       update_scroll_parameters();
  477.       if ( local_x >= 0 AND local_x <= (GLUI_SCROLL_ARROW_WIDTH+box_start_position) )
  478.       {
  479.         return GLUI_SCROLL_STATE_DOWN;
  480.       }
  481.       if ( local_x >= (GLUI_SCROLL_ARROW_WIDTH+box_end_position)
  482.            AND local_x <= (w+GLUI_SCROLL_ARROW_WIDTH) ) 
  483.       {
  484.         return GLUI_SCROLL_STATE_UP;
  485.       }
  486.       return GLUI_SCROLL_STATE_SCROLL;
  487.     }
  488.   }
  489.   else 
  490.   {
  491.     if ( local_x >=  w-GLUI_SCROLL_ARROW_WIDTH-3 && local_x <= w) 
  492.     {
  493.       update_scroll_parameters();
  494.       if ( local_y >= 0 AND local_y <= (GLUI_SCROLL_ARROW_HEIGHT+box_start_position) )
  495.       {
  496.         return GLUI_SCROLL_STATE_UP;
  497.       }
  498.       if ( local_y >= (GLUI_SCROLL_ARROW_HEIGHT+box_end_position)
  499.            AND local_y <= (h+GLUI_SCROLL_ARROW_HEIGHT) )
  500.       {
  501.         return GLUI_SCROLL_STATE_DOWN;
  502.       }
  503.       return GLUI_SCROLL_STATE_SCROLL;
  504.     }
  505.   }
  506.   return GLUI_SCROLL_STATE_NONE;
  507. }
  508. /***************************************** GLUI_Scrollbar::do_click() **********/
  509. void    GLUI_Scrollbar::do_click( void )
  510. {
  511.   int    direction = 0;
  512.   if ( state == GLUI_SCROLL_STATE_UP )
  513.     direction = +1;
  514.   else if ( state == GLUI_SCROLL_STATE_DOWN )
  515.     direction = -1;
  516.   if (data_type==GLUI_SCROLL_INT&&int_min>int_max) direction*=-1;
  517.   if (data_type==GLUI_SCROLL_FLOAT&&float_min>float_max) direction*=-1;
  518.   increase_growth();
  519.   float modifier_factor = 1.0;
  520.   float incr = growth * modifier_factor * user_speed ;
  521.   
  522.   double frame_time=GLUI_Time()-last_update_time;
  523.   double frame_limit=velocity_limit*frame_time;
  524.   if (incr>frame_limit) incr=frame_limit; /* don't scroll faster than limit */
  525.   last_update_time=GLUI_Time();
  526.   float new_val = float_val;
  527.   new_val += direction * incr;
  528.   if (1 || data_type==GLUI_SCROLL_FLOAT) set_float_val(new_val);
  529.   if (0 && data_type==GLUI_SCROLL_INT) set_int_val((int)new_val);
  530.   //printf("do_click: incr %f  val=%f  float_val=%fn",incr,new_val,float_val);
  531.   /*** Now update live variable and do callback.  We don't want
  532.     to do the callback on each iteration of this function, just on every 
  533.     i^th iteration, where i is given by GLUI_SCROLL_CALLBACK_INTERVAL ****/
  534.   callback_count++;
  535.   if ( (callback_count % GLUI_SCROLL_CALLBACK_INTERVAL ) == 0 )
  536.     do_callbacks();
  537. }
  538. /***************************************** GLUI_Scrollbar::do_drag() **********/
  539. void    GLUI_Scrollbar::do_drag( int x, int y )
  540. {
  541.   int   direction = 0;
  542.   float incr, modifier_factor;
  543.   /* int delta_x;              */
  544.   int new_int_val = int_val;
  545.   float new_float_val = float_val;
  546.   int free_len = track_length-box_length;
  547.   if (free_len == 0) return;
  548.   modifier_factor = 1.0;
  549.   if ( state == GLUI_SCROLL_STATE_SCROLL) {
  550.     update_scroll_parameters();
  551.     int hbox = box_length/2;
  552.     if (horizontal) {
  553.       int track_v = x-GLUI_SCROLL_ARROW_WIDTH;
  554.       new_int_val = int_min + (track_v-hbox)*(int_max-int_min)/free_len;
  555.       new_float_val = float_min + (track_v-hbox)*(float_max-float_min)/float(free_len); 
  556.     } else {
  557.       int track_v = y-GLUI_SCROLL_ARROW_HEIGHT;
  558.       new_int_val = int_max - (track_v-hbox)*(int_max-int_min)/free_len;
  559.       new_float_val = float_max - (track_v-hbox)*(float_max-float_min)/float(free_len); 
  560.     }
  561.   }
  562.   else {
  563.     if ( state == GLUI_SCROLL_STATE_UP )
  564.       direction = +1;
  565.     else if ( state == GLUI_SCROLL_STATE_DOWN )
  566.       direction = -1;
  567.     incr = growth * direction * modifier_factor * user_speed;
  568.     new_int_val += direction;
  569.     new_float_val += direction * (float_max-float_min)/free_len;
  570.   }
  571.   last_y = y;
  572.   last_x = x;
  573.   /*** Now update live variable and do callback.  We don't want
  574.     to do the callback on each iteration of this function, just on every 
  575.     i^th iteration, where i is given by GLUI_SCROLL_CALLBACK_INTERVAL ****/
  576.   if(data_type==GLUI_SCROLL_INT)
  577.     set_int_val(new_int_val);
  578.   else if (data_type==GLUI_SCROLL_FLOAT)
  579.     set_float_val(new_float_val);
  580.   callback_count++;
  581.   if ( (callback_count % GLUI_SCROLL_CALLBACK_INTERVAL ) == 0 )
  582.     do_callbacks();
  583. }
  584. /***************************************** GLUI_Scrollbar::needs_idle() ******/
  585. bool GLUI_Scrollbar::needs_idle( void ) const
  586. {
  587.   if  (state == GLUI_SCROLL_STATE_UP OR state == GLUI_SCROLL_STATE_DOWN ) {
  588.     return true;
  589.   }
  590.   else {
  591.     return false;
  592.   }
  593. }
  594. /***************************************** GLUI_Scrollbar::idle() **********/
  595. void    GLUI_Scrollbar::idle( void )
  596. {
  597.   if ( NOT needs_idle() )
  598.     return;
  599.   else
  600.     do_click();
  601. }
  602. /************************************ GLUI_Scrollbar::do_callbacks() **********/
  603. void    GLUI_Scrollbar::do_callbacks( void )
  604. {
  605.   /*    *******************************************/
  606.   if ( NOT first_callback ) {
  607.     if ( data_type == GLUI_SCROLL_INT AND int_val == last_int_val ) {
  608.       return;
  609.     }
  610.     if ( data_type == GLUI_SPINNER_FLOAT AND float_val == last_float_val ) {
  611.       return;
  612.     }
  613.   }
  614.   if (associated_object == NULL) {
  615.     this->execute_callback();
  616.   }
  617.   else  {                      // Use internal Callbacks
  618.     if (object_cb) {
  619.       //object_cb(associated_object, int_val);
  620.       object_cb(this);
  621.     }
  622.   }
  623.   last_int_val   = int_val;
  624.   last_float_val = float_val;
  625.   first_callback = false;
  626. }
  627. /********************************** GLUI_Scrollbar::set_float_val() ************/
  628. void   GLUI_Scrollbar::set_float_val( float new_val )
  629. {
  630.   // Allow for the possibility that the limits are reversed
  631.   float hi = MAX(float_min,float_max);
  632.   float lo = MIN(float_min,float_max);
  633.   if (new_val > hi)
  634.     new_val = hi;
  635.   if (new_val < lo)
  636.     new_val = lo;
  637.   last_float_val = float_val;
  638.   float_val = new_val;
  639.   int_val = (int)new_val;
  640.   redraw();
  641.   /*** Now update the live variable ***/
  642.   output_live(true);
  643. }
  644. /********************************** GLUI_Scrollbar::set_int_val() ************/
  645. void   GLUI_Scrollbar::set_int_val( int new_val )
  646. {
  647.   // Allow for the possibility that the limits are reversed
  648.   int hi = MAX(int_min,int_max);
  649.   int lo = MIN(int_min,int_max);
  650.   if (new_val > hi)
  651.     new_val = hi;
  652.   if (new_val < lo)
  653.     new_val = lo;
  654.   last_int_val = int_val;
  655.   float_val = int_val = new_val;
  656.   redraw();
  657.   /*** Now update the live variable ***/
  658.   output_live(true);
  659. }
  660. /*********************************** GLUI_Scrollbar::set_float_limits() *********/
  661. void   GLUI_Scrollbar::set_float_limits( float low, float high, int limit_type )
  662. {
  663.   if (limit_type != GLUI_LIMIT_CLAMP) {
  664.     // error!
  665.   }
  666.   float_min = low;
  667.   float_max = high;
  668.   // Allow for possiblitly of reversed limits
  669.   float lo = MIN(low,high);
  670.   float hi = MAX(low,high);
  671.   if (float_val<lo) set_float_val(lo);
  672.   if (float_val>hi) set_float_val(hi);
  673. }
  674.  
  675. /*********************************** GLUI_Scrollbar::set_int_limits() *********/
  676. void   GLUI_Scrollbar::set_int_limits( int low, int high, int limit_type )
  677. {
  678.   if (limit_type != GLUI_LIMIT_CLAMP) {
  679.     // error!
  680.   }
  681.   int_min = low;
  682.   int_max = high;    
  683.   // Allow for possiblitly of reversed limits
  684.   int lo = MIN(low,high);
  685.   int hi = MAX(low,high);
  686.   if (int_val<lo) set_int_val(lo);
  687.   if (int_val>hi) set_int_val(hi);
  688.   float_min = low;
  689.   float_max = high;
  690. }
  691.  
  692. /*********************************** GLUI_Scrollbar::reset_growth() *************/
  693. void    GLUI_Scrollbar::reset_growth( void )
  694. {
  695.   growth = fabs(float_max - float_min) / float(GLUI_SCROLL_GROWTH_STEPS);
  696.   if (data_type == GLUI_SCROLL_INT && growth<1) growth=1;
  697. }
  698. /******************************* GLUI_Scrollbar::increase_growth() *************/
  699. void    GLUI_Scrollbar::increase_growth( void )
  700. {
  701.   float range=0;
  702.   if (data_type==GLUI_SCROLL_FLOAT)
  703.     range = fabs(float_max-float_min);
  704.   else 
  705.     range = fabs(float(int_max-int_min));
  706.   if ( growth < (range / float(GLUI_SCROLL_MIN_GROWTH_STEPS)) )
  707.     growth *= growth_exp;
  708.   return;
  709. }