00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef ProgressCounter_h
00022 #define ProgressCounter_h
00023
00024 #include <iosfwd>
00025
00027
00028
00036 class ProgressData {
00037 friend std::ostream & operator<<( std::ostream & str, const ProgressData & obj );
00038
00039 private:
00040
00044 int _min;
00048 int _max;
00052 int _val;
00053
00054 public:
00055
00059 ProgressData( int max_r = 0 )
00060 : _min( 0 )
00061 , _max( max_r )
00062 , _val( 0 )
00063 {}
00067 ProgressData( int min_r, int max_r )
00068 : _min( min_r )
00069 , _max( max_r )
00070 , _val( min_r )
00071 {}
00075 ProgressData( int min_r, int max_r, int val_r )
00076 : _min( min_r )
00077 , _max( max_r )
00078 , _val( val_r )
00079 {}
00083 ProgressData( const ProgressData & rhs )
00084 : _min( rhs._min )
00085 , _max( rhs._max )
00086 , _val( rhs._val )
00087 {}
00088
00092 ProgressData & operator=( const ProgressData & rhs ) {
00093 if ( &rhs != this ) {
00094 init( rhs._min, rhs._max, rhs._val );
00095 }
00096 return *this;
00097 }
00098
00102 virtual ~ProgressData() {}
00103
00104 public:
00105
00109 virtual ProgressData & min( int min_r ) { _min = min_r; return *this; }
00113 virtual ProgressData & max( int max_r ) { _max = max_r; return *this; }
00114
00118 virtual ProgressData & range( int min_r, int max_r ) { _min = min_r; _max = max_r; return *this; }
00122 ProgressData & range( int max_r ) { return range( 0, max_r ); }
00123
00127 virtual ProgressData & set( int val_r ) { _val = val_r; return *this; }
00131 ProgressData & incr( int val_r = 1 ) { return set( _val +val_r ); }
00135 ProgressData & decr( int val_r = 1 ) { return set( _val -val_r ); }
00139 ProgressData & toMin() { return set( _min ); }
00143 ProgressData & toMax() { return set( _max ); }
00144
00148 virtual ProgressData & init( int min_r, int max_r, int val_r ) { _min = min_r; _max = max_r; _val = val_r; return *this; }
00152 ProgressData & init( int min_r, int max_r ) { return init( min_r, max_r, min_r ); }
00156 ProgressData & init( int max_r ) { return init( 0, max_r ); }
00157
00158 public:
00159
00163 int min() const { return _min; }
00164
00168 int max() const { return _max; }
00169
00173 int val() const { return _val; }
00174 };
00175
00177
00179
00180
00191 class ProgressCounter : public ProgressData {
00192 friend std::ostream & operator<<( std::ostream & str, const ProgressCounter & obj );
00193
00194 public:
00195
00196 typedef unsigned Bits;
00197
00201 enum ChangedBit {
00202 VC_NONE = 0x00,
00203
00204 VC_MIN = 0x01,
00205 VC_MAX = 0x02,
00206 VC_VAL = 0x04,
00207 VC_PERCENT = 0x10,
00208
00209 VC_RANGE = (VC_MIN|VC_MAX),
00210 VC_COUNT = (VC_RANGE|VC_VAL),
00211 VC_ALL = (VC_COUNT|VC_PERCENT)
00212 };
00213
00214 private:
00215
00221 mutable Bits _changed;
00222
00226 int _oldPercent;
00227
00231 void check( int lhs, int rhs, ChangedBit which ) { if ( lhs != rhs ) _changed |= which; }
00232
00237 bool checkPercent() const {
00238 if ( _changed & VC_PERCENT )
00239 return true;
00240
00241 if ( (_changed & VC_COUNT) && _oldPercent != percent() ) {
00242 _changed |= VC_PERCENT;
00243 return true;
00244 }
00245 return false;
00246 }
00247
00248 protected:
00249
00254 virtual Bits onUpdate() { return _changed; }
00255
00256 public:
00257
00261 ProgressCounter( Bits initial_r = VC_NONE )
00262 : _changed( initial_r )
00263 , _oldPercent( percent() )
00264 {}
00268 ProgressCounter( const ProgressData & pd_r, Bits initial_r = VC_NONE )
00269 : ProgressData( pd_r )
00270 , _changed( initial_r )
00271 , _oldPercent( percent() )
00272 {}
00273
00277 ProgressCounter & operator=( const ProgressData & pd_r ) {
00278 ProgressData::operator=( pd_r );
00279 return *this;
00280 }
00281
00285 virtual ~ProgressCounter() {}
00286
00287 public:
00288
00292 virtual ProgressData & min( int min_r ) {
00293 check( min(), min_r, VC_MIN );
00294 return ProgressData::min( min_r );
00295 }
00299 ProgressData::min;
00300
00304 virtual ProgressData & max( int max_r ) {
00305 check( max(), max_r, VC_MAX );
00306 return ProgressData::max( max_r );
00307 }
00311 ProgressData::max;
00312
00316 virtual ProgressData & range( int min_r, int max_r ) {
00317 check( min(), min_r, VC_MIN );
00318 check( max(), max_r, VC_MAX );
00319 return ProgressData::range( min_r, max_r );
00320 }
00324 ProgressData::range;
00325
00329 virtual ProgressData & set( int val_r ) {
00330 check( val(), val_r, VC_VAL );
00331 return ProgressData::set( val_r );
00332 }
00333
00337 virtual ProgressData & init( int min_r, int max_r, int val_r ) {
00338 check( min(), min_r, VC_MIN );
00339 check( max(), max_r, VC_MAX );
00340 check( val(), val_r, VC_VAL );
00341 return ProgressData::init( min_r, max_r, val_r );
00342 }
00346 ProgressData::init;
00347
00348 public:
00349
00353 bool newMin() const { return( _changed & VC_MIN ); }
00357 bool newMax() const { return( _changed & VC_MAX ); }
00361 bool newVal() const { return( _changed & VC_VAL ); }
00365 bool newRange() const { return( _changed & VC_RANGE ); }
00369 bool newPercent() const { return checkPercent(); }
00373 bool needsUpdate() const {
00374 checkPercent();
00375 return _changed;
00376 }
00377
00378 public:
00379
00385 double fPercent( double ifepmty_r = 0.0 ) const {
00386 if ( max() == min() ) {
00387 return ifepmty_r;
00388 }
00389 return double( val() - min() ) * 100.0 / double( max() - min() );
00390 }
00396 int percent( int ifepmty_r = 0 ) const {
00397 if ( max() == min() ) {
00398 return ifepmty_r;
00399 }
00400 return (int)fPercent();
00401 }
00402
00403 public:
00404
00408 void tagDirty( Bits bits_r = VC_ALL ) { _changed |= bits_r; }
00412 void setDirty( Bits bits_r = VC_ALL ) { _changed = bits_r; }
00413
00420 Bits update() {
00421 needsUpdate();
00422 Bits ret = onUpdate();
00423 _changed = VC_NONE;
00424 _oldPercent = percent();
00425 return ret;
00426 }
00427
00441 bool updateIfNewPercent( unsigned limit_r = 0 ) {
00442 if ( _changed == VC_ALL ) {
00443
00444 update();
00445 return true;
00446 }
00447 if ( checkPercent() ) {
00448 if ( limit_r ) {
00449 int newpc = percent();
00450 if ( newpc == _oldPercent )
00451 return false;
00452 if ( ! ( newpc == 100 || _oldPercent == 0 || newpc == 0 || _oldPercent == 100 ) ) {
00453 unsigned dist = newpc > _oldPercent ? newpc - _oldPercent
00454 : _oldPercent - newpc;
00455 if ( dist < limit_r )
00456 return false;
00457 }
00458 }
00459 update();
00460 return true;
00461 }
00462 return false;
00463 }
00464
00468 void reset() { init( 0 ); _oldPercent = 0; setDirty(); }
00469
00470 };
00471
00473
00474 #endif // ProgressCounter_h