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

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

initial import for the community edition

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