Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Extras / glui / glui_control.cpp
1 /****************************************************************************
2   
3   GLUI User Interface Toolkit
4   ---------------------------
5
6      glui_control.cpp - top-level GLUI_Control class
7
8
9           --------------------------------------------------
10
11   Copyright (c) 1998 Paul Rademacher
12
13   WWW:    http://sourceforge.net/projects/glui/
14   Forums: http://sourceforge.net/forum/?group_id=92496
15
16   This library is free software; you can redistribute it and/or
17   modify it under the terms of the GNU Lesser General Public
18   License as published by the Free Software Foundation; either
19   version 2.1 of the License, or (at your option) any later version.
20
21   This library is distributed in the hope that it will be useful,
22   but WITHOUT ANY WARRANTY; without even the implied warranty of
23   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24   Lesser General Public License for more details.
25
26   You should have received a copy of the GNU Lesser General Public
27   License along with this library; if not, write to the Free Software
28   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
30 *****************************************************************************/
31
32 #include "glui_internal_control.h"
33
34 int _glui_draw_border_only = 0;
35
36 /*************************** Drawing Utility routines *********************/
37
38 /* Redraw this control. */
39 void          GLUI_Control::redraw(void) {
40     if (glui==NULL || hidden) return;
41     if (glui->should_redraw_now(this))
42       translate_and_draw_front();
43 }
44
45 /** Redraw everybody in our window. */
46 void         GLUI_Control::redraw_window(void) {
47   if (glui==NULL || hidden) return;
48   if ( glui->get_glut_window_id() == -1 ) return;
49   int orig = set_to_glut_window();
50   glutPostRedisplay();
51   restore_window(orig);
52 }
53
54
55
56 /* GLUI_Control::translate_and_draw_front() ********/
57
58 void GLUI_Control::translate_and_draw_front()
59 {
60   GLUI_DRAWINGSENTINAL_IDIOM
61
62   glMatrixMode( GL_MODELVIEW );
63   glPushMatrix();
64   translate_to_origin();
65   draw(0,0);
66   glPopMatrix();
67 }
68
69
70 /********** GLUI_Control::set_to_bkgd_color() ********/
71
72 void GLUI_Control::set_to_bkgd_color( void )
73 {
74   if ( NOT glui )
75     return;
76
77   glColor3ub( glui->bkgd_color.r, glui->bkgd_color.g, glui->bkgd_color.b );
78 }
79
80 /******** GLUI_Control::draw_box_inwards_outline() ********/
81
82 void GLUI_Control::draw_box_inwards_outline( int x_min, int x_max, int y_min, int y_max )
83 {
84   glBegin( GL_LINES );
85   glColor3f( .5, .5, .5 );
86   glVertex2i( x_min, y_min );     glVertex2i( x_max, y_min );
87   glVertex2i( x_min, y_min );     glVertex2i( x_min, y_max );     
88
89   glColor3f( 1., 1., 1. );
90   glVertex2i( x_min, y_max );     glVertex2i( x_max, y_max );
91   glVertex2i( x_max, y_max );     glVertex2i( x_max, y_min );
92
93   if ( enabled )
94     glColor3f( 0., 0., 0. );
95   else
96     glColor3f( .25, .25, .25 );
97
98   glVertex2i( x_min+1, y_min+1 );     glVertex2i( x_max-1, y_min+1 );
99   glVertex2i( x_min+1, y_min+1 );     glVertex2i( x_min+1, y_max-1 );
100
101   glColor3f( .75, .75, .75 );
102   glVertex2i( x_min+1, y_max-1 );     glVertex2i( x_max-1, y_max-1 );
103   glVertex2i( x_max-1, y_max-1 );     glVertex2i( x_max-1, y_min+1 );
104   glEnd();  
105 }
106
107
108 /******* GLUI_Control::draw_box() **********/
109
110 void GLUI_Control::draw_box( int x_min, int x_max, int y_min, int y_max, float r, float g, float b)
111 {
112   if ( r == 1.0 AND g == 1.0 AND b == 1.0 AND NOT enabled AND glui ) {
113     draw_bkgd_box( x_min, x_max, y_min, y_max );
114     return;
115   }
116
117   glColor3f( r, g, b );
118   glBegin( GL_QUADS );
119   glVertex2i( x_min, y_min );       glVertex2i( x_max, y_min );
120   glVertex2i( x_max, y_max );       glVertex2i( x_min, y_max );
121   glEnd();
122 }
123
124
125 /******* GLUI_Control::draw_bkgd_box() **********/
126
127 void GLUI_Control::draw_bkgd_box( int x_min, int x_max, int y_min, int y_max )
128 {
129   set_to_bkgd_color();
130
131   glBegin( GL_QUADS );
132   glVertex2i( x_min, y_min );       glVertex2i( x_max, y_min );
133   glVertex2i( x_max, y_max );       glVertex2i( x_min, y_max );
134   glEnd();
135 }
136
137
138 /**** GLUI_Control::draw_active_area() ********/
139
140 void GLUI_Control::draw_active_box( int x_min, int x_max, int y_min, int y_max )
141 {
142   GLUI_DRAWINGSENTINAL_IDIOM
143
144   if ( active ) {
145     glEnable( GL_LINE_STIPPLE );
146     glLineStipple( 1, 0x5555 );
147     glColor3f( 0., 0., 0. );
148   } else {
149     set_to_bkgd_color();
150   }
151
152   glBegin( GL_LINE_LOOP );
153   glVertex2i(x_min, y_min);      glVertex2i( x_max, y_min );
154   glVertex2i(x_max, y_max);      glVertex2i( x_min, y_max );
155   glEnd();
156   
157   glDisable( GL_LINE_STIPPLE );
158 }
159
160
161 /**** GLUI_Control::draw_emboss_box() ********/
162
163 void   GLUI_Control::draw_emboss_box(int x_min,int x_max,int y_min,int y_max)
164 {
165   glLineWidth( 1.0 );
166   glColor3f( 1.0, 1.0, 1.0 );
167
168   glBegin( GL_LINE_LOOP );
169   glVertex2i( x_min, y_min );    glVertex2i( x_max, y_min );
170   glVertex2i( x_max, y_max );    glVertex2i( x_min, y_max );
171   glEnd();
172  
173   glBegin( GL_LINE_LOOP );
174   glVertex2i( x_min+1, y_min+1 );    glVertex2i( x_max-1, y_min+1 );
175   glVertex2i( x_max-1, y_max-1 );    glVertex2i( x_min+1, y_max-1 );
176   glEnd();
177   
178   glColor3f( .5, .5, .5 );
179   glBegin( GL_LINE_LOOP );
180   glVertex2i( x_min, y_min );
181   glVertex2i( x_max-1, y_min );
182   glVertex2i( x_max-1, y_max-1 );
183   glVertex2i( x_min, y_max-1 );
184   glEnd();
185 }
186
187
188
189 /******* GLUT_Control::draw_recursive() **********/
190
191 void GLUI_Control::draw_recursive( int x, int y )
192 {
193   GLUI_Control *node;
194
195   /*  printf( "%s %d\n", this->name.c_str(), this->hidden );*/
196   if ( NOT can_draw() )
197     return;
198
199   /*if ( 1 ) {  --  Debugging to check control width  
200     glColor3f( 1.0, 0.0, 0.0 );
201     glBegin( GL_LINES );
202     glVertex2i( x_abs, y_abs );00
203     glVertex2i( x_abs+w, y_abs );
204
205     glEnd();
206     }*/
207
208   glMatrixMode( GL_MODELVIEW );
209   glPushMatrix();
210
211   glTranslatef( (float) this->x_abs + .5, 
212                 (float) this->y_abs + .5, 
213                 0.0 );
214
215   if ( NOT _glui_draw_border_only ) {
216     if ( NOT strcmp( name.c_str(), "Rollout" ) ) {
217     }
218
219     this->draw( this->x_off, this->y_off_top );
220   } 
221   else 
222   {
223     if ( this->dynamicCastGLUI_Column() ) {
224       /*   printf( "%s w/h:   %d/%d\n", (char*) name, w, h );              */
225       /*w = 2;              */
226     }
227
228     /* The following draws the area of each control              */
229     glColor3f( 1.0, 0.0, 0.0 );
230     glBegin( GL_LINE_LOOP );
231     glVertex2i( 0, 0 ); glVertex2i( w, 0 );
232     glVertex2i( w, h ); glVertex2i( 0, h );
233     glEnd();
234   }
235   glPopMatrix();
236   
237   node = (GLUI_Control*) first_child();
238   while( node ) {
239     node->draw_recursive( node->x_abs, node->y_abs );
240     node = (GLUI_Control*) node->next();
241   }
242 }
243
244
245 /****** GLUI_Control::set_to_glut_window() *********/
246 /*  Sets the current window to the glut window associated with this control  */
247
248 int GLUI_Control::set_to_glut_window()
249 {
250   int orig_window;
251
252   if ( NOT glui) 
253     return 1;
254
255   orig_window = glutGetWindow();
256
257   glutSetWindow( glui->get_glut_window_id());
258
259   return orig_window;
260 }
261
262
263 /********** GLUI_Control::restore_window() *********/
264
265 void GLUI_Control::restore_window(int orig)
266 {
267   if ( orig > 0 )
268     glutSetWindow( orig );
269 }
270
271
272
273 /****************************** Text ***************************/
274
275 /*************** GLUI_Control::set_font() **********/
276
277 void GLUI_Control::set_font(void *new_font)
278 {
279   font = new_font;
280   redraw();
281 }
282
283
284 /********** GLUI_Control::draw_string() ************/
285
286 void GLUI_Control::draw_string( const char *text )
287 {
288   _glutBitmapString( get_font(), text );
289 }
290
291
292 /**************** GLUI_Control::draw_char() ********/
293
294 void GLUI_Control::draw_char(char c)
295 {
296   glutBitmapCharacter( get_font(), c );
297 }
298
299
300 /*********** GLUI_Control::string_width() **********/
301
302 int GLUI_Control::string_width(const char *text)
303 {
304   return _glutBitmapWidthString( get_font(), text );
305 }
306
307
308 /************* GLUI_Control::char_width() **********/
309
310 int GLUI_Control::char_width(char c)
311 { /* Hash table for faster character width lookups - JVK 
312        Speeds up the textbox a little bit.
313   */
314   int hash_index = c % CHAR_WIDTH_HASH_SIZE;
315   if (char_widths[hash_index][0] != c) {
316     char_widths[hash_index][0] = c;
317     char_widths[hash_index][1] = glutBitmapWidth( get_font(), c );
318   }
319   return char_widths[hash_index][1];
320 }
321
322
323 /*************** GLUI_Control::get_font() **********/
324
325 void *GLUI_Control::get_font( void )
326 {
327   /*** Does this control have its own font? ***/
328   if ( this->font != NULL )
329     return this->font;
330   
331   /*** Does the parent glui have a font? ***/
332   if ( glui )
333     return glui->font;
334
335   /*** Return the default font ***/
336   return GLUT_BITMAP_HELVETICA_12;
337 }
338
339
340 /************* GLUI_Control::draw_name() ***********/
341 /* This draws the name of the control as either black (if enabled), or       */
342 /* embossed if disabled.                                                     */
343
344 void GLUI_Control::draw_name(int x, int y)
345 {
346   if ( NOT can_draw() )
347     return;
348
349   if ( enabled )
350   {
351     set_to_bkgd_color();
352     glRasterPos2i(x+1, y+1);
353     draw_string(name);
354     glColor3b( 0, 0, 0 );
355     glRasterPos2i(x, y);
356     draw_string(name);
357   }
358   else
359   {   /* Control is disabled - emboss the string */
360     glColor3f( 1.0f, 1.0f, 1.0f );
361     glRasterPos2i(x+1, y+1);
362     draw_string(name);
363     glColor3f( .4f, .4f, .4f );
364     glRasterPos2i(x, y);
365     draw_string(name);
366   }
367 }
368
369
370 /**************************** Layout and Packing *********************/
371
372 /****** GLUI_Control::align() **************/
373
374 void GLUI_Control::align()
375 {
376   int  col_x, col_y, col_w, col_h, col_x_off, col_y_off;
377   int  orig_x_abs;
378
379   orig_x_abs = x_abs;
380
381   /* Fix alignment bug relating to columns              */
382   /*return;              */
383
384   if ( NOT parent() )
385     return;  /* Clearly this shouldn't happen, though */
386
387   get_this_column_dims(&col_x, &col_y, &col_w, &col_h, 
388                        &col_x_off, &col_y_off);
389
390   if ( this->dynamicCastGLUI_Column() ) {
391     /*          if ( this->prev() != NULL ) {
392                 ((GLUI_Control*)prev())->get_this_column_dims(&col_x, &col_y, &col_w, &col_h, 
393                 &col_x_off, &col_y_off);
394                 
395                 x_abs = col_x + col_w;
396                 }
397                 else {
398                 x_abs = ((GLUI_Control*)parent())->x_abs;
399                 }
400                 */
401     return;
402   }
403
404   if ( alignment == GLUI_ALIGN_LEFT ) {
405     x_abs = col_x + col_x_off;
406   }
407   else if ( alignment == GLUI_ALIGN_RIGHT ) {
408     x_abs = col_x + col_w - col_x_off - this->w;
409   }
410   else if ( alignment == GLUI_ALIGN_CENTER ) {
411     x_abs = col_x + (col_w - this->w) / 2;
412   }
413
414   if ( this->is_container ) {
415     /***   Shift all child columns   ***/
416     int delta = x_abs - orig_x_abs;
417
418     GLUI_Control *node;
419                 
420     node = (GLUI_Control*) this->first_child();
421     while( node != NULL ) {
422       if ( node->dynamicCastGLUI_Column() ) { 
423         node->x_abs += delta;
424       } 
425
426       node = (GLUI_Control*) node->next();
427     }
428   }
429
430 }
431
432
433 /************** GLUI_Control::pack() ************/
434 /* Recalculate positions and offsets  */
435
436 void GLUI_Control::pack_old(int x, int y)
437 {
438   GLUI_Control  *node;
439   int            max_w, curr_y, curr_x, max_y;
440   int            x_in = x, y_in =y;
441   int            x_margin, y_margin_top, y_margin_bot;
442   int            y_top_column;
443   int            column_x;
444   GLUI_Column   *curr_column = NULL;
445   this->update_size();
446   x_margin     = this->x_off;
447   y_margin_top = this->y_off_top;
448   y_margin_bot = this->y_off_bot;
449   this->x_abs = x_in;
450   this->y_abs = y_in;
451   max_w  = -1;
452   max_y  = -1;
453   curr_x = this->x_abs + x_margin;
454   curr_y = this->y_abs + y_margin_top;
455   /*** Record start of this set of columns ***/
456   y_top_column = curr_y;
457   column_x     = 0;
458   if ( this == glui->main_panel ) {
459     x=x;
460   }
461   /*** Iterate over children, packing them first ***/
462   node = (GLUI_Control*) this->first_child();
463   while( node != NULL ) {
464           if ( node->dynamicCastGLUI_Panel() && !node->collapsible) { 
465       /* Pad some space above fixed size panels */
466       curr_y += GLUI_ITEMSPACING;
467     } 
468           else if ( node->dynamicCastGLUI_Column()) {
469       curr_column = (GLUI_Column*) node;
470       if ( 1 ) {
471         column_x += max_w + 2 * x_margin;
472         curr_x  += max_w + 2 * x_margin;
473       }
474       else {
475         column_x += max_w + 0 * x_margin;
476         curr_x  += max_w + 0 * x_margin;
477       }
478       /*node->pack( curr_x, curr_y );              */
479       node->x_abs = curr_x;
480       node->y_abs = y_top_column;
481       node->w     = 2;
482       node->h     = curr_y - y_top_column;
483       curr_x  += x_margin * 3 + 40;
484       curr_y  = y_top_column;
485       max_w = 0;
486       node = (GLUI_Control*) node->next();
487       continue;
488     }
489     node->pack( curr_x, curr_y );
490         if ( node->dynamicCastGLUI_Panel() && !node->collapsible)  
491       /* Pad some space below fixed size panels */
492       curr_y += GLUI_ITEMSPACING;
493     curr_y  += node->h;
494     if ( node->w > max_w ) {
495       max_w = node->w;
496       if ( curr_column != NULL )
497         curr_column->w = max_w;
498     }
499     node = (GLUI_Control*) node->next();
500     if ( node ) {
501       curr_y += GLUI_ITEMSPACING;
502     }
503     if ( curr_y > max_y )
504       max_y = curr_y;
505   }
506   if ( this->is_container ) {
507     max_y += y_margin_bot;  /*** Add bottom border inside box */
508     if ( this->first_child() ) {
509                 if ( this->dynamicCastGLUI_Rollout() ) {        
510         /**  We don't want the rollout to shrink in width when it's
511           closed **/
512         this->w = MAX(this->w, column_x + max_w + 2 * x_margin );
513       }
514       else {
515         this->w        = column_x + max_w + 2 * x_margin;
516       }
517       this->h        = (max_y - y_in);
518     }
519     else  {            /* An empty container, so just assign default w & h */
520       this->w        = GLUI_DEFAULT_CONTROL_WIDTH;
521       this->h        = GLUI_DEFAULT_CONTROL_HEIGHT;
522     }
523     /** Expand panel if necessary (e.g., to include all the text in 
524       a panel label) **/
525     this->update_size();   
526   }
527 }
528
529 /*** GLUI_Control::get_this_column_dims() **********/
530 /* Gets the x,y,w,h,and x/y offsets of the column to which a control belongs */
531
532 void    GLUI_Control::get_this_column_dims( int *col_x, int *col_y, 
533                                             int *col_w, int *col_h, 
534                                             int *col_x_off, int *col_y_off )
535 {
536   GLUI_Control *node, *parent_ptr;
537   int           parent_h, parent_y_abs;
538
539   parent_ptr = (GLUI_Control*) parent();
540
541   if ( parent_ptr==NULL )
542     return;
543
544   parent_h     = parent_ptr->h;
545   parent_y_abs = parent_ptr->y_abs;
546   
547   if ( parent_ptr->dynamicCastGLUI_Panel() AND
548        parent_ptr->int_val == GLUI_PANEL_EMBOSSED AND
549        parent_ptr->name != "" ) {
550     parent_h -= GLUI_PANEL_EMBOSS_TOP;
551     parent_y_abs += GLUI_PANEL_EMBOSS_TOP;
552   }
553
554   if ( 0 ) {
555     GLUI_Node *first, *last, *curr;
556
557     /**   Look for first control in this column   **/
558     first = this;
559     while (first->prev() AND !(first->prev())->dynamicCastGLUI_Column() ) 
560       first = first->prev();
561
562     /**   Look for last control in this column    **/
563     last = this;
564     while ( last->next() AND !(first->next())->dynamicCastGLUI_Column() )
565       last = last->next();
566
567     curr = first;
568     int max_w = -1;
569     do {
570       if ( ((GLUI_Control*)curr)->w > max_w )
571         max_w = ((GLUI_Control*)curr)->w;
572
573       if ( curr == last )
574         break;
575
576       curr = curr->next();
577     } while( curr != NULL );
578
579     *col_x     = ((GLUI_Control*)first)->x_abs;
580     *col_y     = ((GLUI_Control*)first)->y_abs;
581     *col_w     = max_w;
582     if ( parent() ) {
583       *col_h     = ((GLUI_Control*)parent())->h;
584       *col_x_off = ((GLUI_Control*)parent())->x_off;
585     }
586     else {
587       *col_h = 10;
588       *col_x_off = 0;
589     }
590     *col_y_off = 0;
591
592     return;
593   }
594
595   if ( 1 ) {    /* IS THIS WRONG? */
596     /*** Look for preceding column ***/
597     node = (GLUI_Control*) this->prev();
598     while( node ) {
599                 if ( node->dynamicCastGLUI_Column() ) {
600         *col_x     = node->x_abs;
601         *col_y     = parent_y_abs;
602         *col_w     = node->w;
603         *col_h     = parent_h;
604         *col_x_off = node->x_off;
605         *col_y_off = 0;
606
607         return;
608       }
609
610       node = (GLUI_Control*) node->prev();
611     }
612
613     /*** Nope, Look for next column ***/
614     node = (GLUI_Control*) this->next();
615     while( node ) {
616       if ( node->dynamicCastGLUI_Column() ) {
617         *col_x     = parent_ptr->x_abs;
618         *col_y     = parent_y_abs;
619         *col_w     = node->x_abs - parent_ptr->x_abs;
620         *col_h     = parent_h;
621         *col_x_off = node->x_off;
622         *col_y_off = 0;
623
624         return;
625       }
626
627       node = (GLUI_Control*) node->next();
628     }
629
630     /***   This is single-column panel, so return panel dims   ***/
631     *col_x     = parent_ptr->x_abs;
632     *col_y     = parent_y_abs;
633     *col_w     = parent_ptr->w;
634     *col_h     = parent_h;
635     *col_x_off = parent_ptr->x_off;
636     *col_y_off = 0;
637   }
638 }
639
640
641 void    GLUI_Control::pack( int x, int y )
642 {
643   GLUI_Control  *node;
644   int            max_w, curr_y, curr_x, max_y;
645   int            x_in = x, y_in =y;
646   int            x_margin, y_margin_top, y_margin_bot;
647   int            y_top_column;
648   int            column_x;
649   GLUI_Column   *curr_column = NULL;
650
651   this->update_size();
652
653   x_margin     = this->x_off;
654   y_margin_top = this->y_off_top;
655   y_margin_bot = this->y_off_bot;
656   
657   this->x_abs = x_in;
658   this->y_abs = y_in;
659
660   max_w  = 0;
661   max_y  = 0;
662   curr_x = this->x_abs + x_margin;
663   curr_y = this->y_abs + y_margin_top;
664
665   /*** Record start of this set of columns ***/
666
667   y_top_column = curr_y;
668   column_x     = curr_x;
669
670   /*** Iterate over children, packing them first ***/
671
672   node = (GLUI_Control*) this->first_child();
673   while( node != NULL ) {
674           if ( node->dynamicCastGLUI_Panel() && !node->collapsible) { 
675       /* Pad some space above fixed-size panels */
676       curr_y += GLUI_ITEMSPACING;
677     } 
678     else if ( node->dynamicCastGLUI_Column() ) {
679       curr_column = (GLUI_Column*) node;
680       curr_x   += max_w + 1 * x_margin;
681       column_x  = curr_x;
682
683       node->x_abs = curr_x;
684       node->y_abs = y_top_column;
685       node->w     = 2;
686       node->h     = curr_y - y_top_column;
687
688       curr_x  += x_margin * 1;
689       curr_y  = y_top_column;
690       max_w = 0;
691
692       node = (GLUI_Control*) node->next();
693       continue;
694     }
695                 
696     node->pack( curr_x, curr_y );
697
698         if ( node->dynamicCastGLUI_Panel()  && !node->collapsible)
699       /* Pad some space below fixed-size panels */
700       curr_y += GLUI_ITEMSPACING;
701     
702     curr_y  += node->h;
703
704     if ( node->w > max_w ) {
705       max_w = node->w;
706       if ( curr_column != NULL )
707         curr_column->w = max_w + x_margin;
708     }
709
710     if ( curr_y > max_y ) {
711       max_y = curr_y;
712       if ( curr_column != NULL )
713         curr_column->h = max_y - y_top_column;
714     }
715
716     node = (GLUI_Control*) node->next();
717     
718     if ( node ) {
719       curr_y += GLUI_ITEMSPACING;
720     }
721
722   }
723
724   if ( this->is_container ) {
725     max_y += y_margin_bot;  /*** Add bottom border inside box */
726
727     if ( this->first_child() ) {
728       this->w        = column_x + max_w + 2 * x_margin - x_in;
729       this->h        = (max_y - y_in);
730     }
731     else  {            /* An empty container, so just assign default w & h */
732                 if ( !this->dynamicCastGLUI_Rollout() &&
733                   !this->dynamicCastGLUI_Tree() ) {
734         this->w        = GLUI_DEFAULT_CONTROL_WIDTH;
735         this->h        = GLUI_DEFAULT_CONTROL_HEIGHT;
736       }
737     }
738
739     /** Expand panel if necessary (e.g., to include all the text in 
740       a panel label) **/
741     this->update_size();   
742
743
744     /*** Now we step through the GLUI_Columns, setting the 'h'  ***/
745     node = (GLUI_Control*) this->first_child();
746     while( node != NULL ) {
747       if ( node->dynamicCastGLUI_Column() ) {
748         node->h = this->h - y_margin_bot - y_margin_top;
749       }
750
751       node = (GLUI_Control*) node->next();
752     }
753   }
754 }
755
756
757
758 /******************************** Live Variables **************************/
759 /*********** GLUI_Control::sync_live() ************/
760 /* Reads live variable and sets control to its current value                */
761 /* This function is recursive, and operates on control's children           */
762
763 void GLUI_Control::sync_live(int recurse, int draw_it)
764 {
765   GLUI_Node *node;
766   int        sync_it=true;
767   int        i;
768   float      *fp;
769   bool       changed = false;
770
771   /*** If this is currently active control, and mouse button is down,
772     don't sync ***/
773   if ( glui )
774   {
775     if ( this == glui->active_control AND glui->mouse_button_down )
776       sync_it = false;
777
778     /*** Actually, just disable syncing if button is down ***/
779     /*** Nope, go ahead and sync if mouse is down - this allows syncing in
780       callbacks ***/
781     if ( 0 ) { /* THIS CODE BELOW SHOULD NOT BE EXECUTED */
782       if ( glui->mouse_button_down ) {
783         /* printf( "Can't sync\n" );              */
784         return;
785       }
786     }
787   }
788
789   /***  If this control has a live variable, we check its current value
790     against the stored value in the control  ***/
791
792   if ( ptr_val != NULL ) {
793     if ( live_type == GLUI_LIVE_NONE OR NOT sync_it ) {
794     }
795     else if ( live_type == GLUI_LIVE_INT ) {
796       if ( *((int*)ptr_val) != last_live_int ) {
797         set_int_val( *((int*)ptr_val) );
798         last_live_int = *((int*)ptr_val);
799         changed = true;
800       }
801     }   
802     else if ( live_type == GLUI_LIVE_FLOAT ) {
803       if ( *((float*)ptr_val) != last_live_float ) {
804         set_float_val( *((float*)ptr_val) );
805         last_live_float = *((float*)ptr_val);
806         changed = true;
807       }
808     } 
809     else if ( live_type == GLUI_LIVE_TEXT ) {
810       if ( last_live_text.compare((const char*)ptr_val) != 0 ) {
811         set_text( (char*) ptr_val );
812         last_live_text = (const char*)ptr_val;
813         changed = true;
814       }
815     } 
816     else if ( live_type == GLUI_LIVE_STRING ) {
817       if ( last_live_text.compare(((std::string*) ptr_val)->c_str()) != 0 ) {
818         set_text( ((std::string*) ptr_val)->c_str());
819         last_live_text = *((std::string*) ptr_val);
820         changed = true;
821       }
822     } 
823     else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) { 
824       /***  Step through the arrays, and see if they're the same  ***/
825       
826       fp = (float*) ptr_val;
827       for ( i=0; i<float_array_size; i++ ) {
828         if ( *fp != last_live_float_array[i] ) {
829           changed = true;
830           break;
831         }
832                 
833         fp++;
834       }
835       
836       if ( changed == true) {
837         fp = (float*) ptr_val;
838         set_float_array_val( fp );
839         for ( i=0; i<float_array_size; i++ ) {
840           last_live_float_array[i] = *fp;
841           fp++;
842         }
843       }
844     }
845     else if ( live_type == GLUI_LIVE_DOUBLE ) {
846     }
847   }
848
849   /***  If this control is changed and we're supposed to be drawing, then
850     draw it now    ***/
851   if ( changed == true AND draw_it ) {
852     redraw();
853   }
854
855   if ( recurse ) {
856     /*** Now recursively output live vars for all children ***/
857     node = this->first_child();
858     while( node ) {
859       ((GLUI_Control*) node)->sync_live(true, true);
860       node = node->next();
861     }
862
863     if ( collapsible == true AND is_open == false ) {
864       /** Here we have a collapsed control (e.g., a rollout that is closed **/
865       /** We need to go in and sync all the collapsed controls inside      **/
866        
867       node = this->collapsed_node.first_child();
868       while( node ) {
869         ((GLUI_Control*) node)->sync_live(true, false);
870         node = node->next();
871       }
872     }
873   }
874 }
875
876
877 /********** GLUI_Control::output_live() ************/
878 /* Writes current value of control to live variable.                         */
879
880 void GLUI_Control::output_live(int update_main_gfx)
881 {
882   int    i;
883   float *fp;
884
885   if ( ptr_val == NULL )
886     return;
887    
888   if ( NOT live_inited ) 
889     return;
890    
891   if ( live_type == GLUI_LIVE_NONE ) {
892   }
893   else if ( live_type == GLUI_LIVE_INT ) {
894     *((int*)ptr_val) = int_val;
895     last_live_int    = int_val;
896   } 
897   else if ( live_type == GLUI_LIVE_FLOAT ) {
898     *((float*)ptr_val) = float_val;
899     last_live_float    = float_val;
900   } 
901   else if ( live_type == GLUI_LIVE_TEXT ) {
902     strncpy( (char*) ptr_val, text.c_str(), text.length()+1);
903     last_live_text =  text;
904   } 
905   else if ( live_type == GLUI_LIVE_STRING ) {
906     (*(std::string*)ptr_val)= text.c_str();
907     last_live_text =  text;
908   } 
909   else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
910     fp = (float*) ptr_val;
911
912     for( i=0; i<float_array_size; i++ ) {
913       *fp                      = float_array_val[i];
914       last_live_float_array[i] = float_array_val[i];
915       fp++;
916     }
917   }
918   else if ( live_type == GLUI_LIVE_DOUBLE ) {
919   }
920
921   /** Update the main gfx window? **/
922   if ( update_main_gfx AND this->glui != NULL ) {
923     this->glui->post_update_main_gfx();
924   }
925 }
926
927
928 /****** GLUI_Control::execute_callback() **********/
929
930 void GLUI_Control::execute_callback()
931 {
932   int old_window;
933   
934   old_window = glutGetWindow();
935
936   if ( glui AND glui->main_gfx_window_id != -1 ) 
937     glutSetWindow( glui->main_gfx_window_id );
938
939   this->callback( this );
940 //  if ( this->callback ) 
941 //    this->callback( this->user_id );
942
943   glutSetWindow( old_window );
944 }
945
946
947 /************** GLUI_Control::init_live() **********/
948 /* Reads in  value of a live variable.  Called once, when ctrl is created   */
949
950 void GLUI_Control::init_live()
951 {
952   int    i;
953   float *fp;
954
955   if ( ptr_val == NULL )
956     return;
957
958   if ( live_type == GLUI_LIVE_NONE ) {
959   }
960   else if ( live_type == GLUI_LIVE_INT ) {
961     set_int_val( *((int*)ptr_val) );
962     last_live_int = *((int*)ptr_val);
963   } 
964   else if ( live_type == GLUI_LIVE_FLOAT ) {
965     set_float_val( *((float*)ptr_val) );
966     last_live_float = *((float*)ptr_val);
967   } 
968   else if ( live_type == GLUI_LIVE_TEXT ) {
969     set_text( (const char*) ptr_val );
970     last_live_text = (const char*) ptr_val;
971   }
972   else if ( live_type == GLUI_LIVE_STRING ) {
973     set_text( ((std::string*) ptr_val)->c_str() );
974     last_live_text = ((std::string*) ptr_val)->c_str();
975   }
976   else if ( live_type == GLUI_LIVE_FLOAT_ARRAY ) {
977     set_float_array_val( (float*) ptr_val );
978
979     fp = (float*) ptr_val;
980
981     for( i=0; i<float_array_size; i++ ) {
982       last_live_float_array[i] = *fp;
983       fp++;
984     }
985
986   }
987   else if ( live_type == GLUI_LIVE_DOUBLE ) {
988   }
989
990   live_inited = true;
991 }
992
993 /***** GLUI_Control::set_float_array_val() ********/
994
995 void  GLUI_Control::set_float_array_val( float *array_ptr )
996 {
997   int i;
998
999   if ( array_ptr == NULL )
1000     return;
1001
1002   for( i=0; i<float_array_size; i++ ) {
1003     float_array_val[i] = array_ptr[i];
1004   }
1005
1006   /*** Output the live var, without updating the main gfx window ***/
1007   output_live(false);
1008 }
1009
1010
1011 /***** GLUI_Control::get_float_array_val() ********/
1012
1013 void  GLUI_Control::get_float_array_val( float *array_ptr )
1014 {
1015   int i;
1016
1017   if ( array_ptr == NULL )
1018     return;
1019
1020   for( i=0; i<float_array_size; i++ ) {
1021     array_ptr[i] = float_array_val[i];
1022   }
1023 }
1024
1025
1026
1027 /**************************** Little Utility Routines ********************/
1028
1029 /**** GLUI_Control::set_name() ********************/
1030
1031 void   GLUI_Control::set_name( const char *str )
1032 {
1033   name = str;
1034   redraw(); 
1035 }
1036
1037 /**** GLUI_Control::enable() ****************/
1038
1039 void GLUI_Control::enable()
1040 {
1041   GLUI_Control *node;
1042
1043   enabled = true;
1044    
1045   if ( NOT glui )
1046     return;
1047
1048   redraw();
1049
1050   /*** Now recursively enable all buttons below it ***/
1051   node = (GLUI_Control*) first_child();
1052   while(node)
1053   {
1054     node->enable();
1055     node = (GLUI_Control*) node->next();
1056   }
1057 }
1058
1059
1060 /***** GLUI_Control::disable() ****************/
1061
1062 void GLUI_Control::disable()
1063 {
1064   GLUI_Control *node;
1065
1066   enabled = false;
1067   
1068   if ( NOT glui )
1069     return;
1070
1071   if ( glui->active_control == this )
1072     glui->deactivate_current_control();
1073   redraw();
1074
1075   /*** Now recursively disable all buttons below it ***/
1076   node = (GLUI_Control*) first_child();
1077   while(node) {
1078     node->disable();
1079     node = (GLUI_Control*) node->next();
1080   }
1081 }
1082
1083 /******* GLUI_Control::set_w() **************/
1084
1085 void GLUI_Control::set_w(int new_w)
1086 {
1087   w = new_w;
1088   update_size();  /* Make sure control is big enough to fit text */
1089   if (glui) glui->refresh();
1090 }
1091
1092
1093 /**** GLUI_Control::set_h() **************/
1094
1095 void GLUI_Control::set_h(int new_h)
1096 {
1097   h = new_h;
1098   update_size();  /* Make sure control is big enough to fit text */
1099   if (glui) glui->refresh();
1100 }
1101
1102
1103 /***** GLUI_Control::set_alignment() ******/
1104
1105 void GLUI_Control::set_alignment(int new_align)
1106 {
1107   alignment = new_align;
1108
1109   if ( glui )
1110   {
1111     glui->align_controls(this);
1112     redraw_window();
1113   }
1114 }
1115
1116
1117 /***** GLUI_Control::needs_idle() *********/
1118 /* This method gets overloaded by specific classes, e.g. Spinner.            */
1119 /* It returns whether or not a control needs to receive an idle event or not */
1120 /* For example, a spinner only needs idle events when the user is holding    */
1121 /* the mouse down in one of the arrows.  Otherwise, don't waste cycles       */
1122 /* and OpenGL context switching by calling its idle.                         */
1123
1124 bool GLUI_Control::needs_idle() const
1125
1126   return false; 
1127 }
1128
1129
1130 /********* GLUI_Control::~GLUI_Control() **********/
1131
1132 GLUI_Control::~GLUI_Control()
1133 {
1134   GLUI_Control *item = (GLUI_Control*) this->first_child();
1135
1136   while (item) 
1137   {
1138     GLUI_Control *tmp = item;
1139     item = (GLUI_Control*) item->next();
1140     delete tmp;
1141   }
1142 }
1143
1144 /********* GLUI_Control::hide_internal() ********/
1145 /** Sets hidden==true for this  control and all its siblings.             */
1146 /**  If recurse is true, we go to children as well                       */
1147
1148 void         GLUI_Control::hide_internal( int recurse )
1149 {
1150   GLUI_Node *node;
1151
1152   node = (GLUI_Node *) this;
1153   while( node != NULL ) {
1154     ((GLUI_Control*)node)->hidden = true;
1155
1156     if ( recurse AND node->first_child() != NULL )  
1157       ((GLUI_Control*) node->first_child())->hide_internal(true);
1158       
1159     node = node->next();
1160   }
1161
1162   node = this->collapsed_node.first_child();
1163   while( node != NULL ) {
1164     ((GLUI_Control*)node)->hidden = true;
1165
1166     if ( recurse AND node->first_child() != NULL )  
1167       ((GLUI_Control*) node->first_child())->hide_internal(true);
1168       
1169     node = node->next();
1170   }
1171 }
1172
1173
1174 /********* GLUI_Control::unhide_internal() ********/
1175 /** Sets hidden==false for this  control and all its siblings.             */
1176 /**  If recurse is true, we go to children as well                       */
1177
1178 void         GLUI_Control::unhide_internal( int recurse )
1179 {
1180   GLUI_Node *node;
1181
1182   node = (GLUI_Node *) this;
1183   while( node != NULL ) {
1184     /*    printf( "unhide: %s [%d]\n", ((GLUI_Control*)node)->name.c_str(), 
1185             ((GLUI_Control*)node)->hidden );*/
1186     ((GLUI_Control*)node)->hidden = false;
1187
1188     if ( recurse AND node->first_child() != NULL )  
1189       ((GLUI_Control*) node->first_child())->unhide_internal(true);
1190       
1191     node = node->next();
1192   }
1193
1194   node = this->collapsed_node.first_child();
1195   while( node != NULL ) {
1196     ((GLUI_Control*)node)->hidden = false;
1197
1198     if ( recurse AND node->first_child() != NULL )  
1199       ((GLUI_Control*) node->first_child())->unhide_internal(true);
1200       
1201     node = node->next();
1202   }
1203 }