"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 }