Flu_Collapsable_Group.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // $Id: Flu_Collapsable_Group.cpp,v 1.8 2004/06/17 14:16:42 jbryan Exp $
  2. /***************************************************************
  3. * FLU - FLTK Utility Widgets
  4. * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University
  5. *
  6. * This file and its content is protected by a software license.
  7. * You should have received a copy of this license with this file.
  8. * If not, please contact the Ohio Supercomputer Center immediately:
  9. * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212
  10. *
  11. ***************************************************************/
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <FL/Fl_Window.H>
  17. #include "FLU/Flu_Collapsable_Group.H"
  18. Flu_Collapsable_Group :: Flu_Collapsable_Group( int x, int y, int w, int h, const char *l )
  19. : Fl_Group( x, y, w, h ), button( x, y, w, 20 ), group( x, y+20, w, h-20 )
  20. {
  21. _originalHeight = h;
  22. _changing = false;
  23. _collapseTime = 0.25f;
  24. _fps = 60.0f;
  25. _fit = false;
  26. _open = true;
  27. _currentHeight = h;
  28. label( l );
  29. box( FL_EMBOSSED_BOX );
  30. align( FL_ALIGN_LEFT );
  31. // the group label is actually used by the button. so since we don't want this group's label
  32. // to show up, draw it under everything
  33. Fl_Group::align( FL_ALIGN_CENTER );
  34. Fl_Group::add( &button );
  35. button.callback( _collapseCB, this );
  36. button.align( FL_ALIGN_CENTER | FL_ALIGN_CLIP );
  37. Fl_Group::add( &group );
  38. Fl_Group::resizable( group );
  39. Fl_Group::end();
  40. group.begin();
  41. }
  42. void Flu_Collapsable_Group :: resize( int x, int y, int w, int h )
  43. {
  44. // skip over our parent's resize since we don't want it to mess with the children
  45. Fl_Widget::resize( x, y, w, h );
  46. button.resize( x, y, w, 20 );
  47. group.resize( x, y+20, w, h-20 );
  48. }
  49. void Flu_Collapsable_Group :: open( bool o )
  50. {
  51. _open = o;
  52. do_callback();
  53. if( !_changing )
  54. {
  55. _oldResizable = group.resizable();
  56. group.resizable( NULL );
  57. }
  58. if( _open )
  59. {
  60. group.show();
  61. _newHeight = _originalHeight;
  62. }
  63. else
  64. {
  65. _newHeight = button.h()+5;
  66. if( !_changing )
  67. _originalHeight = h();
  68. }
  69. _currentHeight = float(h());
  70. if( !_changing )
  71. {
  72. _timeout = 1.0f / _fps;
  73. _deltaHeight = ( float(_newHeight) - _currentHeight ) / ( _collapseTime * _fps );
  74. _changing = true;
  75. Fl::add_timeout( _timeout, _updateCB, this );
  76. }
  77. }
  78. void Flu_Collapsable_Group :: updateCB()
  79. {
  80. // update the height
  81. _currentHeight += _deltaHeight;
  82. // see if we're done with the animation
  83. if( ( _deltaHeight == 0.0f ) ||
  84. ( ( _deltaHeight > 0.0f ) && ( _currentHeight >= float(_newHeight) ) ) ||
  85. ( ( _deltaHeight < 0.0f ) && ( _currentHeight <= float(_newHeight) ) ) )
  86. {
  87. resize( x(), y(), w(), _newHeight );
  88. if( !_open )
  89. group.hide();
  90. _changing = false;
  91. group.resizable( _oldResizable );
  92. }
  93. else
  94. {
  95. resize( x(), y(), w(), int(_currentHeight) );
  96. Fl::repeat_timeout( _timeout, _updateCB, this );
  97. }
  98. // redraw the group
  99. redraw();
  100. group.redraw();
  101. // wierd hack to get parent to redraw everything (necessary since our size has changed)
  102. if( parent() )
  103. parent()->init_sizes();
  104. if( this->window() )
  105. this->window()->redraw();
  106. }
  107. void Flu_Collapsable_Group :: draw()
  108. {
  109. int X;
  110. FluSimpleString l = open() ? "- " : "+ ";
  111. l += label();
  112. button.label( l.c_str() );
  113. // force fit the button if necessary
  114. if( _fit )
  115. button.size( w()-12, button.labelsize()+6 );
  116. else
  117. {
  118. // otherwise make it as big as its label
  119. int W = 0, H = 0;
  120. fl_font( button.labelfont(), button.labelsize() );
  121. fl_measure( button.label(), W, H );
  122. button.size( W+6, button.h() );
  123. }
  124. // align the button
  125. if( align() & FL_ALIGN_LEFT )
  126. X = 4;
  127. else if( align() & FL_ALIGN_RIGHT )
  128. X = w() - button.w() - 8;
  129. else
  130. X = w()/2 - button.w()/2 - 2;
  131. // draw the main group box
  132. if( damage() & ~FL_DAMAGE_CHILD )
  133. fl_draw_box( box(), x(), y()+button.h()/2, w(), h()-button.h()/2, color() );
  134. // clip and draw the internal group
  135. fl_clip( x()+2, y()+button.h()+1, w()-4, h()-button.h()-3 );
  136. if( _changing )
  137. {
  138. if( !_open )
  139. group.resize( x(), y()-_originalHeight+(int)_currentHeight+20, w(), _originalHeight );
  140. else
  141. group.resize( x(), y()-_newHeight+(int)_currentHeight+20, w(), _newHeight );
  142. }
  143. draw_child( group );
  144. fl_pop_clip();
  145. // clear behind the button, resize, and draw
  146. fl_color( color() );
  147. fl_rectf( x()+X, y(), button.w()+4, button.h() );
  148. button.position( x()+X+2, y() );
  149. draw_child( button );
  150. button.label( 0 );
  151. }