Flu_Chat_Buffer.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // $Id: Flu_Chat_Buffer.cpp,v 1.8 2004/11/17 12:40:32 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 <FL/fl_draw.H>
  13. #include "FLU/Flu_Chat_Buffer.H"
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #define X_OFFSET 5
  18. Flu_Chat_Buffer :: Flu_Chat_Buffer( int x, int y, int w, int h, const char *label )
  19. : Fl_Widget( x, y, w, h, label )
  20. {
  21. buffer = NULL;
  22. scrollbar = new Fl_Scrollbar( x+w-20, y+2, 18, h-4 );
  23. scrollbar->linesize( 1 );
  24. scrollbar->callback( _scrollbarCB, this );
  25. box( FL_DOWN_BOX );
  26. color( FL_WHITE );
  27. setSystemStyle( FL_HELVETICA_ITALIC, FL_RED );
  28. setRemoteHandleStyle( FL_HELVETICA_BOLD, FL_BLACK );
  29. setLocalHandleStyle( FL_HELVETICA_BOLD, FL_BLUE );
  30. setRemoteMessageStyle( FL_HELVETICA, FL_BLACK );
  31. setLocalMessageStyle( FL_HELVETICA, FL_BLUE );
  32. clear();
  33. }
  34. Flu_Chat_Buffer :: ~Flu_Chat_Buffer()
  35. {
  36. clear( 0 );
  37. }
  38. void Flu_Chat_Buffer :: draw()
  39. {
  40. if( recomputeFootprint )
  41. _computeMessageFootprint();
  42. // draw the background box
  43. draw_box();
  44. // resize the scrollbar to be a constant width
  45. scrollbar->resize( x()+w()-20, y()+2, 18, h()-4 );
  46. scrollbar->redraw();
  47. int height = h()-4;
  48. int line;
  49. if( ( currentLine == 0 ) && ( totalLines == 0 ) )
  50. return;
  51. line = currentLine - 1 - scrollbar->value();
  52. fl_push_clip( x()+2, y()+2, w()-4, h()-4 );
  53. while( height >= 0 )
  54. {
  55. switch( buffer[line].type )
  56. {
  57. case 'S':
  58. {
  59. height -= buffer[line].height;
  60. fl_color( systemColor );
  61. fl_font( systemFont, FL_NORMAL_SIZE );
  62. fl_draw( buffer[line].message, x()+X_OFFSET, y()+height,
  63. buffer[line].messageW, buffer[line].height, (Fl_Align)(FL_ALIGN_TOP_LEFT | FL_ALIGN_WRAP), NULL, 0 );
  64. }
  65. break;
  66. case 'R':
  67. {
  68. height -= buffer[line].height;
  69. fl_color( remoteHandleColor );
  70. fl_font( remoteHandleFont, FL_NORMAL_SIZE );
  71. fl_draw( buffer[line].handle, x()+X_OFFSET, y()+height,
  72. buffer[line].handleW, buffer[line].height, (Fl_Align)(FL_ALIGN_TOP_LEFT | FL_ALIGN_WRAP), NULL, 0 );
  73. fl_color( remoteMessageColor );
  74. fl_font( remoteMessageFont, FL_NORMAL_SIZE );
  75. fl_draw( buffer[line].message, x()+X_OFFSET+buffer[line].handleW, y()+height,
  76. buffer[line].messageW, buffer[line].height, (Fl_Align)(FL_ALIGN_TOP_LEFT | FL_ALIGN_WRAP), NULL, 0 );
  77. }
  78. break;
  79. case 'L':
  80. {
  81. height -= buffer[line].height;
  82. fl_color( localHandleColor );
  83. fl_font( localHandleFont, FL_NORMAL_SIZE );
  84. fl_draw( buffer[line].handle, x()+X_OFFSET, y()+height,
  85. buffer[line].handleW, buffer[line].height, (Fl_Align)(FL_ALIGN_TOP_LEFT | FL_ALIGN_WRAP), NULL, 0 );
  86. fl_color( localMessageColor );
  87. fl_font( localMessageFont, FL_NORMAL_SIZE );
  88. fl_draw( buffer[line].message, x()+X_OFFSET+buffer[line].handleW, y()+height,
  89. buffer[line].messageW, buffer[line].height, (Fl_Align)(FL_ALIGN_TOP_LEFT | FL_ALIGN_WRAP), NULL, 0 );
  90. }
  91. break;
  92. }
  93. if( ( line == 0 ) && ( totalLines < maxLines ) )
  94. break;
  95. if( line == 0 )
  96. line = totalLines - 1;
  97. else
  98. line--;
  99. }
  100. fl_pop_clip();
  101. }
  102. void Flu_Chat_Buffer :: scrollbarCB()
  103. {
  104. redraw();
  105. }
  106. void Flu_Chat_Buffer :: _addMessage( char type, char *handle, char *msg )
  107. {
  108. buffer[currentLine].type = type;
  109. buffer[currentLine].handle = handle;
  110. buffer[currentLine].message = msg;
  111. // increment the current line, and wrap to the beginning of the buffer
  112. // if necessary
  113. currentLine = (currentLine+1) % maxLines;
  114. // increment the total lines (no more than maxLines)
  115. totalLines = ( totalLines < maxLines ) ? totalLines+1 : maxLines;
  116. recomputeFootprint = true;
  117. redraw();
  118. }
  119. void Flu_Chat_Buffer :: addSystemMessage( const char *msg )
  120. {
  121. if( !buffer || !msg )
  122. return;
  123. if( strlen( msg ) == 0 )
  124. return;
  125. _addMessage( 'S', NULL, strdup(msg) );
  126. }
  127. void Flu_Chat_Buffer :: addRemoteMessage( const char *handle, const char *msg )
  128. {
  129. if( !buffer || !handle || !msg )
  130. return;
  131. if( ( strlen( handle ) == 0 ) || ( strlen( msg ) == 0 ) )
  132. return;
  133. _addMessage( 'R', strdup(handle), strdup(msg) );
  134. }
  135. void Flu_Chat_Buffer :: addLocalMessage( const char *handle, const char *msg )
  136. {
  137. if( !buffer || !handle || !msg )
  138. return;
  139. if( ( strlen( handle ) == 0 ) || ( strlen( msg ) == 0 ) )
  140. return;
  141. _addMessage( 'L', strdup(handle), strdup(msg) );
  142. }
  143. void Flu_Chat_Buffer :: clear( int maximumLines )
  144. {
  145. recomputeFootprint = true;
  146. if( buffer )
  147. {
  148. for( int i = 0; i < maxLines; i++ )
  149. {
  150. if( buffer[i].handle )
  151. free( buffer[i].handle );
  152. if( buffer[i].message )
  153. free( buffer[i].message );
  154. }
  155. free( buffer );
  156. buffer = NULL;
  157. }
  158. maxLines = maximumLines;
  159. if( maxLines == 0 )
  160. return;
  161. buffer = (MessageInfo*)malloc( maxLines * sizeof(MessageInfo) );
  162. for( int i = 0; i < maxLines; i++ )
  163. {
  164. buffer[i].handle = buffer[i].message = NULL;
  165. buffer[i].type = 0; // empty
  166. }
  167. totalLines = currentLine = 0;
  168. }
  169. void Flu_Chat_Buffer :: _computeMessageFootprint()
  170. {
  171. recomputeFootprint = false;
  172. // restrict the width calculation to account for the scrollbar
  173. int width = w() - scrollbar->w() - X_OFFSET;
  174. int linesPastHeight = 0;
  175. int totalHeight = 0;
  176. for( int i = 0; i < totalLines; i++ )
  177. {
  178. switch( buffer[i].type )
  179. {
  180. case 'S':
  181. {
  182. int tw = width, th;
  183. // set the font and color for system messages
  184. fl_color( systemColor );
  185. fl_font( systemFont, FL_NORMAL_SIZE );
  186. // measure how big the message is
  187. fl_measure( buffer[i].message, tw, th );
  188. buffer[i].messageW = tw;
  189. buffer[i].height = th;
  190. totalHeight += buffer[i].height;
  191. if( totalHeight > h() )
  192. linesPastHeight++;
  193. }
  194. break;
  195. case 'R':
  196. {
  197. int tw = width, hh, mh;
  198. // set the font and color for remote handles
  199. fl_color( remoteHandleColor );
  200. fl_font( remoteHandleFont, FL_NORMAL_SIZE );
  201. // measure how big the handle is
  202. fl_measure( buffer[i].handle, tw, hh );
  203. buffer[i].handleW = tw;
  204. // set the font and color for remote messages, and adjust the width so the message
  205. // is aligned with the end of the handle
  206. fl_color( remoteMessageColor );
  207. fl_font( remoteMessageFont, FL_NORMAL_SIZE );
  208. tw = width - tw;
  209. // measure how big the message is
  210. fl_measure( buffer[i].message, tw, mh );
  211. buffer[i].messageW = tw;
  212. // increase total height by max of handle height and message height
  213. buffer[i].height = ( mh > hh ) ? mh : hh;
  214. totalHeight += buffer[i].height;
  215. if( totalHeight > h() )
  216. linesPastHeight++;
  217. }
  218. break;
  219. case 'L':
  220. {
  221. int tw = width, hh, mh;
  222. // set the font and color for local handles
  223. fl_color( localHandleColor );
  224. fl_font( localHandleFont, FL_NORMAL_SIZE );
  225. // measure how big the handle is
  226. fl_measure( buffer[i].handle, tw, hh );
  227. buffer[i].handleW = tw;
  228. // set the font and color for local messages, and adjust the width so the message
  229. // is aligned with the end of the handle
  230. fl_color( localMessageColor );
  231. fl_font( localMessageFont, FL_NORMAL_SIZE );
  232. tw = width - tw;
  233. // measure how big the message is
  234. fl_measure( buffer[i].message, tw, mh );
  235. buffer[i].messageW = tw;
  236. // increase total height by max of handle height and message height
  237. buffer[i].height = ( mh > hh ) ? mh : hh;
  238. totalHeight += buffer[i].height;
  239. if( totalHeight > h() )
  240. linesPastHeight++;
  241. }
  242. break;
  243. }
  244. }
  245. scrollbar->range( linesPastHeight, 0 );
  246. float size = float(h()) / float(totalHeight);
  247. if( size > 1.0f )
  248. size = 1.0f;
  249. if( size < 0.08f )
  250. size = 0.08f;
  251. scrollbar->slider_size( size );
  252. redraw();
  253. }
  254. void Flu_Chat_Buffer :: resize( int x, int y, int w, int h )
  255. {
  256. Fl_Widget::resize( x, y, w, h );
  257. recomputeFootprint = true;
  258. }