"Fossies" - the Fresh Open Source Software Archive

Member "xosview-1.23/fieldmeter.cc" (11 Jul 2020, 8765 Bytes) of package /linux/misc/xosview-1.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fieldmeter.cc" see the Fossies "Dox" file reference documentation.

    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 #include "fieldmeter.h"
    8 #include <stdio.h>
    9 #include <stdlib.h>
   10 #include <string.h>
   11 #include <math.h>
   12 #include <iostream>
   13 
   14 
   15 FieldMeter::FieldMeter( XOSView *parent, int numfields, const char *title,
   16                         const char *legend, int docaptions, int dolegends,
   17                         int dousedlegends )
   18 : Meter(parent, title, legend, docaptions, dolegends, dousedlegends){
   19     /*  We need to set print_ to something valid -- the meters
   20      *  apparently get drawn before the meters have a chance to call
   21      *  CheckResources() themselves.  */
   22   numWarnings_ = printedZeroTotalMesg_ = 0;
   23   print_ = PERCENT;
   24   metric_ = false;
   25   usedoffset_ = 0;
   26   used_ = 0;
   27   lastused_ = -1;
   28   fields_ = NULL;
   29   colors_ = NULL;
   30   lastvals_ = NULL;
   31   lastx_ = NULL;
   32   setNumFields(numfields);
   33 }
   34 
   35 void
   36 FieldMeter::disableMeter ( )
   37 {
   38   setNumFields(1);
   39   setfieldcolor (0, "gray");
   40   Meter::legend ("Disabled");
   41   // And specify the total of 1.0, so the meter is grayed out.
   42   total_ = 1.0;
   43   fields_[0] = 1.0;
   44 }
   45 
   46 
   47 FieldMeter::~FieldMeter( void ){
   48   delete[] fields_;
   49   delete[] colors_;
   50   delete[] lastvals_;
   51   delete[] lastx_;
   52 }
   53 
   54 void FieldMeter::checkResources( void ){
   55   Meter::checkResources();
   56   usedcolor_ = parent_->allocColor( parent_->getResource( "usedLabelColor") );
   57 }
   58 
   59 
   60 void FieldMeter::SetUsedFormat ( const char * const fmt ) {
   61     /*  Do case-insensitive compares.  */
   62   if (!strncasecmp (fmt, "percent", 8))
   63     print_ = PERCENT;
   64   else if (!strncasecmp (fmt, "autoscale", 10))
   65     print_ = AUTOSCALE;
   66   else if (!strncasecmp (fmt, "float", 6))
   67     print_ = FLOAT;
   68   else {
   69     std::cerr << "Error:  could not parse format of '" << fmt << "'.\n"
   70               << "  I expected one of 'percent', 'autoscale', or 'float'"
   71               << " (Case-insensitive)." << std::endl;
   72     exit(1);
   73   }
   74 }
   75 
   76 void FieldMeter::setUsed (double val, double total)
   77 {
   78   if (print_ == FLOAT)
   79     used_ = val;
   80   else if (print_ == PERCENT)
   81   {
   82     if (total != 0.0)
   83       used_ = val / total * 100.0;
   84     else
   85     {
   86       if (!printedZeroTotalMesg_) {
   87         printedZeroTotalMesg_ = 1;
   88         std::cerr << "Warning: " << name() << " meter had a zero total field! "
   89                   << "Would have caused a div-by-zero exception." << std::endl;
   90       }
   91       used_ = 0.0;
   92     }
   93   }
   94   else if (print_ == AUTOSCALE)
   95     used_ = val;
   96   else {
   97     std::cerr << "Error in " << name() << ":  I can't handle a UsedType enum "
   98               << "value of " << print_ << "!" << std::endl;
   99     exit(1);
  100   }
  101 }
  102 
  103 void FieldMeter::reset( void ){
  104   for ( int i = 0 ; i < numfields_ ; i++ )
  105     lastvals_[i] = lastx_[i] = -1;
  106 }
  107 
  108 void FieldMeter::setfieldcolor( int field, const char *color ){
  109   colors_[field] = parent_->allocColor( color );
  110 }
  111 
  112 void FieldMeter::setfieldcolor( int field, unsigned long color ) {
  113   colors_[field] = color;
  114 }
  115 
  116 void FieldMeter::draw( void ){
  117     /*  Draw the outline for the fieldmeter.  */
  118   parent_->setForeground( parent_->foreground() );
  119   parent_->drawRectangle( x_ - 1, y_ - 1, width_ + 2, height_ + 2 );
  120   if ( dolegends_ ){
  121     parent_->setForeground( textcolor_ );
  122 
  123     int offset;
  124     if ( dousedlegends_ )
  125       offset = parent_->textWidth( "XXXXXXXXXX" );
  126     else
  127       offset = parent_->textWidth( "XXXXXX" );
  128 
  129     parent_->drawString( x_ - offset + 1, y_ + height_, title_ );
  130   }
  131 
  132   drawlegend();
  133   drawfields( 1 );
  134 }
  135 
  136 void FieldMeter::drawlegend( void ){
  137   char *tmp1, *tmp2, buff[100];
  138   int n, x = x_;
  139 
  140   if (!docaptions_ || !dolegends_)
  141     return;
  142 
  143   parent_->clear( x_, y_ - 5 - parent_->textHeight(),
  144                   width_ + 5, parent_->textHeight() + 4 );
  145 
  146   tmp1 = tmp2 = legend_;
  147   for ( int i = 0 ; i < numfields_ ; i++ ){
  148     n = 0;
  149     while ( (*tmp2 != '/') && (*tmp2 != '\0') ){
  150       if ( (*tmp2 == '\\') && (*(tmp2 + 1) == '/') ) // allow '/' in field as '\/'
  151         memmove( tmp2, tmp2 + 1, strlen(tmp2) );
  152       tmp2++;
  153       n++;
  154     }
  155     tmp2++;
  156     strncpy( buff, tmp1, n );
  157     buff[n] = '\0';
  158     parent_->setStippleN(i%4);
  159     parent_->setForeground( colors_[i] );
  160     parent_->drawString( x, y_ - 5, buff );
  161     x += parent_->textWidth( buff, n );
  162     parent_->setForeground( parent_->foreground() );
  163     if ( i != numfields_ - 1 )
  164       parent_->drawString( x, y_ - 5, "/" );
  165     x += parent_->textWidth( "/", 1 );
  166     tmp1 = tmp2;
  167   }
  168   parent_->setStippleN(0);  /*  Restore default all-bits stipple.  */
  169 }
  170 
  171 void FieldMeter::drawused( int mandatory ){
  172   if ( !mandatory )
  173     if ( lastused_ == used_ )
  174       return;
  175 
  176   parent_->setStippleN(0);  /*  Use all-bits stipple.  */
  177   static const int onechar = parent_->textWidth( "X" );
  178   if (!usedoffset_)  // metric meters need extra space for '-' sign
  179     usedoffset_ = ( metric_ ? parent_->textWidth( "XXXXXX" )
  180                             : parent_->textWidth( "XXXXX" ) );
  181   char buf[10];
  182 
  183   if (print_ == PERCENT){
  184     snprintf( buf, 10, "%d%%", (int)used_ );
  185   }
  186   else if (print_ == AUTOSCALE){
  187     char scale[2];
  188     double scaled_used = scaleValue(used_, scale, metric_);
  189     /*  For now, we can only print 3 characters, plus the optional sign and
  190      *  suffix, without overprinting the legends.  Thus, we can
  191      *  print 965, or we can print 34, but we can't print 34.7 (the
  192      *  decimal point takes up one character).  bgrayson   */
  193     if (scaled_used == 0.0)
  194       snprintf (buf, 10, "0");
  195     else {
  196       if (scaled_used < 0 && !metric_)
  197         snprintf (buf, 10, "-");
  198       else if ( fabs(scaled_used) < 9.95 )
  199         //  9.95 or above would get
  200         //  rounded to 10.0, which is too wide.
  201         snprintf (buf, 10, "%.1f%s", scaled_used, scale);
  202       else
  203         snprintf (buf, 10, "%.0f%s", scaled_used, scale);
  204     }
  205   }
  206   else {
  207     if ( fabs(used_) < 99.95 )
  208       snprintf( buf, 10, "%.1f", used_ );
  209     else  // drop the decimal if the string gets too long
  210       snprintf( buf, 10, "%.0f", used_ );
  211   }
  212 
  213   parent_->clear( x_ - usedoffset_, y_ + height_ - parent_->textHeight(),
  214                   usedoffset_ - onechar / 2, parent_->textHeight() + 1 );
  215   parent_->setForeground( usedcolor_ );
  216   parent_->drawString( x_ - (strlen( buf ) + 1 ) * onechar + 2,
  217                        y_ + height_, buf );
  218   lastused_ = used_;
  219 }
  220 
  221 void FieldMeter::drawfields( int mandatory ){
  222   int twidth, x = x_;
  223 
  224   if ( total_ == 0 )
  225     return;
  226 
  227   for ( int i = 0 ; i < numfields_ ; i++ ){
  228     /*  Look for bogus values.  */
  229     if (fields_[i] < 0.0 && !metric_) {
  230       /*  Only print a warning 5 times per meter, followed by a
  231        *  message about no more warnings.  */
  232       numWarnings_ ++;
  233       if (numWarnings_ < 5)
  234         std::cerr << "Warning: meter " << name() << " had a negative value of "
  235                   << fields_[i] << " for field " << i << std::endl;
  236       if (numWarnings_ == 5)
  237         std::cerr << "Future warnings from the " << name() << " meter will not "
  238                   << "be displayed." << std::endl;
  239     }
  240 
  241     twidth = (int)fabs(((width_ * fields_[i]) / total_));
  242     if ( (i == numfields_ - 1) && ((x + twidth) != (x_ + width_)) )
  243       twidth = width_ + x_ - x;
  244 
  245     if ( mandatory || (twidth != lastvals_[i]) || (x != lastx_[i]) ){
  246       parent_->setForeground( colors_[i] );
  247       parent_->setStippleN(i%4);
  248       parent_->drawFilledRectangle( x, y_, twidth, height_ );
  249       parent_->setStippleN(0);  /*  Restore all-bits stipple.  */
  250       lastvals_[i] = twidth;
  251       lastx_[i] = x;
  252     }
  253     x += twidth;
  254   }
  255   if ( dousedlegends_ )
  256     drawused( mandatory );
  257 }
  258 
  259 void FieldMeter::checkevent( void ){
  260   drawfields(0);
  261 }
  262 
  263 void FieldMeter::setNumFields(int n){
  264   numfields_ = n;
  265   delete[] fields_;
  266   delete[] colors_;
  267   delete[] lastvals_;
  268   delete[] lastx_;
  269   fields_ = new double[numfields_];
  270   colors_ = new unsigned long[numfields_];
  271   lastvals_ = new int[numfields_];
  272   lastx_ = new int[numfields_];
  273 
  274   total_ = 0;
  275   for ( int i = 0 ; i < numfields_ ; i++ ){
  276     fields_[i] = 0.0;             /* egcs 2.91.66 bug !? don't do this and */
  277     lastvals_[i] = lastx_[i] = 0; /* that in a single statement or it'll   */
  278                                   /* overwrite too much with 0 ...         */
  279                   /* Thomas Waldmann ( tw@com-ma.de )      */
  280   }
  281 }
  282 
  283 bool FieldMeter::checkX(int x, int width) const {
  284   if ((x < x_) || (x + width < x_)
  285       || (x > x_ + width_) || (x + width > x_ + width_)){
  286     std::cerr << "FieldMeter::checkX() : bad horiz values for meter : "
  287          << name() << std::endl;
  288 
  289     std::cerr <<"value "<<x<<", width "<<width<<", total_ = "<<total_<<std::endl;
  290 
  291     for (int i = 0 ; i < numfields_ ; i++)
  292       std::cerr <<"fields_[" <<i <<"] = " <<fields_[i] <<",";
  293     std::cerr <<std::endl;
  294 
  295     return false;
  296   }
  297 
  298   return true;
  299 }