root/foundation-apps/grosview-maxx/bitfieldmeter.cc

Revision 2, 10.9 KB (checked in by emasson, 3 years ago)

initial import for the community edition

Line 
1//
2//  Copyright (c) 1999, 2006 Thomas Waldmann ( ThomasWaldmann@gmx.de )
3//  based on work of Mike Romberg ( mike.romberg@noaa.gov )
4//
5//  This file may be distributed under terms of the GPL
6//
7//
8#ifdef HAVE_FSTREAM
9#include <fstream>
10#else
11#include <fstream.h>
12#endif
13#include <stdlib.h>
14#include "general.h"
15#include "bitfieldmeter.h"
16#include "xosview.h"
17
18
19BitFieldMeter::BitFieldMeter( XOSView *parent, int numBits, int numfields,
20                        const char *title,
21                        const char *bitslegend, const char *FieldLegend,
22                        int docaptions, int dolegends, int dousedlegends )
23: Meter(parent, title, bitslegend, docaptions, dolegends, dousedlegends){
24    /*  We need to set print_ to something valid -- the meters
25     *  apparently get drawn before the meters have a chance to call
26     *  CheckResources() themselves.  */
27  bits_ = NULL;
28  lastbits_ = NULL;
29  numWarnings_ = printedZeroTotalMesg_ = 0;
30  print_ = PERCENT;
31  used_ = 0;
32  lastused_ = -1;
33  fields_ = NULL;
34  colors_ = NULL;
35  lastvals_ = NULL;
36  lastx_ = NULL;
37  setNumBits(numBits);
38  fieldLegend_ = NULL;
39  setfieldlegend(FieldLegend);
40  setNumFields(numfields);
41}
42
43void
44BitFieldMeter::disableMeter ( )
45{
46  setNumFields(1);
47  setfieldcolor (0, "grey");
48  setfieldlegend ("Disabled");
49  total_ = fields_[0] = 1.0;
50  setNumBits(1);
51  offColor_ = onColor_ = parent_->allocColor("grey");
52}
53
54
55BitFieldMeter::~BitFieldMeter( void ){
56  delete[] bits_;
57  delete[] lastbits_;
58  delete[] fields_;
59  delete[] colors_;
60  delete[] lastvals_;
61  delete[] lastx_;
62}
63
64void BitFieldMeter::checkResources( void ){
65  Meter::checkResources();
66  usedcolor_ = parent_->allocColor( parent_->getResource( "usedLabelColor") );
67}
68
69
70void BitFieldMeter::setNumBits(int n){
71  numbits_ = n;
72  delete[] bits_;
73  delete[] lastbits_;
74
75  bits_ = new char[numbits_];
76  lastbits_ = new char[numbits_];
77
78  for ( int i = 0 ; i < numbits_ ; i++ )
79      bits_[i] = lastbits_[i] = 0;
80}
81
82void BitFieldMeter::SetUsedFormat ( const char * const fmt ) {
83    /*  Do case-insensitive compares.  */
84  if (!strncasecmp (fmt, "percent", 8))
85    print_ = PERCENT;
86  else if (!strncasecmp (fmt, "autoscale", 10))
87    print_ = AUTOSCALE;
88  else if (!strncasecmp (fmt, "float", 6))
89    print_ = FLOAT;
90  else
91  {
92    fprintf (stderr, "Error:  could not parse format of '%s'\n", fmt);
93    fprintf (stderr, "  I expected one of 'percent', 'bytes', or 'float'\n");
94    fprintf (stderr, "  (Case-insensitive)\n");
95    exit(1);
96  }
97}
98
99void BitFieldMeter::setUsed (float val, float total)
100{
101  if (print_ == FLOAT)
102    used_ = val;
103  else if (print_ == PERCENT)
104  {
105    if (total != 0.0)
106      used_ = val / total * 100.0;
107    else
108    {
109      if (!printedZeroTotalMesg_) {
110        printedZeroTotalMesg_ = 1;
111        fprintf(stderr, "Warning:  %s meter had a zero total "
112                "field!  Would have caused a div-by-zero "
113                "exception.\n", name());
114      }
115      used_ = 0.0;
116    }
117  }
118  else if (print_ == AUTOSCALE)
119    used_ = val;
120  else {
121    fprintf (stderr, "Error in %s:  I can't handle a "
122                     "UsedType enum value of %d!\n", name(), print_);
123    exit(1);
124  }
125}
126
127void BitFieldMeter::reset( void ){
128  for ( int i = 0 ; i < numfields_ ; i++ )
129    lastvals_[i] = lastx_[i] = -1;
130}
131
132void BitFieldMeter::setfieldcolor( int field, const char *color ){
133  colors_[field] = parent_->allocColor( color );
134}
135
136void BitFieldMeter::setfieldcolor( int field, unsigned long color ) {
137  colors_[field] = color;
138}
139
140
141void BitFieldMeter::draw( void ){
142    /*  Draw the outline for the fieldmeter.  */
143  parent_->setForeground( parent_->foreground() );
144  parent_->lineWidth( 1 );
145  parent_->drawFilledRectangle( x_ - 1, y_ - 1, width_/2 + 2, height_ + 2 );
146
147// ??  parent_->lineWidth( 0 );
148
149  parent_->drawRectangle( x_ + width_/2 +3, y_ - 1, width_/2 - 2, height_ + 2 );
150  if ( dolegends_ ){
151    parent_->setForeground( textcolor_ );
152
153    int offset;
154    if ( dousedlegends_ )
155      offset = parent_->textWidth( "XXXXXXXXX" );
156    else
157      offset = parent_->textWidth( "XXXXX" );
158
159    parent_->drawString( x_ - offset + 1, y_ + height_, title_ );
160
161    if(docaptions_){
162      parent_->setForeground( onColor_ );
163      parent_->drawString( x_, y_ - 5, legend_ );
164      drawfieldlegend();
165    }
166  }
167  drawBits( 1 );
168  drawfields( 1 );
169}
170
171void BitFieldMeter::drawfieldlegend( void ){
172  char *tmp1, *tmp2, buff[100];
173  int n, x = x_ + width_/2 + 4;
174
175  tmp1 = tmp2 = fieldLegend_;
176  for ( int i = 0 ; i < numfields_ ; i++ ){
177    n = 0;
178    while ( (*tmp2 != '/') && (*tmp2 != '\0') ){
179      tmp2++;
180      n++;
181    }
182    tmp2++;
183    strncpy( buff, tmp1, n );
184    buff[n] = '\0';
185    parent_->setStippleN(i%4);
186    parent_->setForeground( colors_[i] );
187    parent_->drawString( x, y_ - 5, buff );
188    x += parent_->textWidth( buff, n );
189    parent_->setForeground( parent_->foreground() );
190    if ( i != numfields_ - 1 )
191      parent_->drawString( x, y_ - 5, "/" );
192    x += parent_->textWidth( "/", 1 );
193    tmp1 = tmp2;
194  }
195  parent_->setStippleN(0);      /*  Restore default all-bits stipple.  */
196}
197
198void BitFieldMeter::drawused( int manditory ){
199  if ( !manditory )
200    if ( (lastused_ == used_) )
201      return;
202
203  parent_->setStippleN(0);      /*  Use all-bits stipple.  */
204  static const int onechar = parent_->textWidth( "X" );
205  static int xoffset = parent_->textWidth( "XXXXX" );
206
207  char buf[10];
208
209  if (print_ == PERCENT){
210    snprintf( buf, 10, "%d%%", (int)used_ );
211  }
212  else if (print_ == AUTOSCALE){
213    char scale;
214    float scaled_used;
215      /*  Unfortunately, we have to do our comparisons by 1000s (otherwise
216       *  a value of 1020, which is smaller than 1K, could end up
217       *  being printed as 1020, which is wider than what can fit)  */
218      /*  However, we do divide by 1024, so a K really is a K, and not
219       *  1000.  */
220      /*  In addition, we need to compare against 999.5*1000, because
221       *  999.5, if not rounded up to 1.0 K, will be rounded by the
222       *  %.0f to be 1000, which is too wide.  So anything at or above
223       *  999.5 needs to be bumped up.  */
224    if (used_ >= 999.5*1000*1000*1000*1000*1000*1000)
225        {scale='E'; scaled_used = used_/1024/1024/1024/1024/1024/1024;}
226    else if (used_ >= 999.5*1000*1000*1000*1000)
227        {scale='P'; scaled_used = used_/1024/1024/1024/1024/1024;}
228    else if (used_ >= 999.5*1000*1000*1000)
229        {scale='T'; scaled_used = used_/1024/1024/1024/1024;}
230    else if (used_ >= 999.5*1000*1000)
231        {scale='G'; scaled_used = used_/1024/1024/1024;}
232    else if (used_ >= 999.5*1000)
233        {scale='M'; scaled_used = used_/1024/1024;}
234    else if (used_ >= 999.5)
235        {scale='K'; scaled_used = used_/1024;}
236    else {scale=' '; scaled_used = used_;}
237      /*  For now, we can only print 3 characters, plus the optional
238       *  suffix, without overprinting the legends.  Thus, we can
239       *  print 965, or we can print 34, but we can't print 34.7 (the
240       *  decimal point takes up one character).  bgrayson   */
241    if (scaled_used == 0.0)
242      snprintf (buf, 10, "0");
243    else if (scaled_used < 9.95)  //  9.95 or above would get
244                                  //  rounded to 10.0, which is too wide.
245      snprintf (buf, 10, "%.1f%c", scaled_used, scale);
246    /*  We don't need to check against 99.5 -- it all gets %.0f.  */
247    /*else if (scaled_used < 99.5)*/
248      /*snprintf (buf, 10, "%.0f%c", scaled_used, scale);*/
249    else
250      snprintf (buf, 10, "%.0f%c", scaled_used, scale);
251  }
252  else {
253    snprintf( buf, 10, "%.1f", used_ );
254  }
255
256  parent_->clear( x_ - xoffset, y_ + height_ - parent_->textHeight(),
257                 xoffset - onechar / 2, parent_->textHeight() + 1 );
258  parent_->setForeground( usedcolor_ );
259  parent_->drawString( x_ - (strlen( buf ) + 1 ) * onechar + 2,
260                      y_ + height_, buf );
261
262  lastused_ = used_;
263}
264
265void BitFieldMeter::drawBits( int manditory ){
266  static int pass = 1;
267
268//  pass = (pass + 1) % 2;
269
270  int x1 = x_, w;
271
272  w = (width_/2 - (numbits_+1)) / numbits_;
273
274  for ( int i = 0 ; i < numbits_ ; i++ ){
275    if ( (bits_[i] != lastbits_[i]) || manditory ){
276      if ( bits_[i] && pass )
277        parent_->setForeground( onColor_ );
278      else
279        parent_->setForeground( offColor_ );
280      parent_->drawFilledRectangle( x1, y_, w, height_);
281    }
282
283    lastbits_[i] = bits_[i];
284
285    x1 += (w + 2);
286  }
287}
288
289void BitFieldMeter::drawfields( int manditory ){
290  int twidth, x = x_ + width_/2 + 4;
291
292  if ( total_ == 0 )
293    return;
294
295  for ( int i = 0 ; i < numfields_ ; i++ ){
296    /*  Look for bogus values.  */
297    if (fields_[i] < 0.0) {
298      /*  Only print a warning 5 times per meter, followed by a
299       *  message about no more warnings.  */
300      numWarnings_ ++;
301      if (numWarnings_ < 5)
302        fprintf(stderr, "Warning:  meter %s had a negative "
303          "value of %f for field %d\n", name(), fields_[i], i);
304      if (numWarnings_ == 5)
305        fprintf(stderr, "Future warnings from the %s meter "
306          "will not be displayed.\n", name());
307    }
308
309    twidth = (int) (((width_/2 - 3) * (float) fields_[i]) / total_);
310//    twidth = (int)((fields_[i] * width_) / total_);
311    if ( (i == numfields_ - 1) && ((x + twidth) != (x_ + width_)) )
312      twidth = width_ + x_ - x;
313
314    if ( manditory || (twidth != lastvals_[i]) || (x != lastx_[i]) ){
315      parent_->setForeground( colors_[i] );
316      parent_->setStippleN(i%4);
317      parent_->drawFilledRectangle( x, y_, twidth, height_ );
318      parent_->setStippleN(0);  /*  Restore all-bits stipple.  */
319      lastvals_[i] = twidth;
320      lastx_[i] = x;
321
322      if ( dousedlegends_ )
323        drawused( manditory );
324    }
325    x += twidth;
326  }
327
328  //parent_->flush();
329}
330
331void BitFieldMeter::checkevent( void ){
332    drawBits();
333    drawfields();
334}
335
336void BitFieldMeter::setBits(int startbit, unsigned char values){
337  unsigned char mask = 1;
338  for (int i = startbit ; i < startbit + 8 ; i++){
339    bits_[i] = values & mask;
340    mask = mask << 1;
341  }
342}
343
344void BitFieldMeter::setNumFields(int n){
345  numfields_ = n;
346  delete[] fields_;
347  delete[] colors_;
348  delete[] lastvals_;
349  delete[] lastx_;
350  fields_ = new float[numfields_];
351  colors_ = new unsigned long[numfields_];
352  lastvals_ = new int[numfields_];
353  lastx_ = new int[numfields_];
354
355  total_ = 0;
356  for ( int i = 0 ; i < numfields_ ; i++ ){
357    fields_[i] = 0.0;             /* egcs 2.91.66 bug !? don't do this and */
358    lastvals_[i] = lastx_[i] = 0; /* that in a single statement or it'll   */
359                                  /* overwrite too much with 0 ...         */
360                                  /* Thomas Waldmann ( tw@com-ma.de )      */
361  }
362}
363
364bool BitFieldMeter::checkX(int x, int width) const {
365  if ((x < x_) || (x + width < x_)
366      || (x > x_ + width_) || (x + width > x_ + width_)){
367    std::cerr << "BitFieldMeter::checkX() : bad horiz values for meter : "
368         << name() << std::endl;
369
370    std::cerr <<"value "<<x<<", width "<<width<<", total_ = "<<total_<<std::endl;
371
372    for (int i = 0 ; i < numfields_ ; i++)
373      std::cerr <<"fields_[" <<i <<"] = " <<fields_[i] <<",";
374    std::cerr <<std::endl;
375
376    return false;
377  }
378
379  return true;
380}
381
382
383void BitFieldMeter::setfieldlegend( const char *fieldlegend ){
384  delete[] fieldLegend_;
385  int len = strlen(fieldlegend);
386  fieldLegend_ = new char[len + 1];
387  strncpy( fieldLegend_, fieldlegend, len );
388  fieldLegend_[len] = '\0'; // strncpy() will not null terminate if s2 > len
389}
Note: See TracBrowser for help on using the browser.