00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "CeylanLocatable.h"
00028
00029 #include "CeylanMatrix.h"
00030 #include "CeylanLogPlug.h"
00031 #include "CeylanUtils.h"
00032 #include "CeylanOperators.h"
00033 #include "CeylanTypes.h"
00034
00035
00036 #ifdef CEYLAN_USES_CONFIG_H
00037 #include "CeylanConfig.h"
00038 #endif // CEYLAN_USES_CONFIG_H
00039
00040
00041 using std::string ;
00042
00043
00044 using namespace Ceylan ;
00045 using namespace Ceylan::Log ;
00046 using namespace Ceylan::Maths::Linear ;
00047
00048
00049
00050
00051 LocatableException::LocatableException( const string & message ) :
00052 Ceylan::Exception( "Locatable exception: " + message )
00053 {
00054
00055 }
00056
00057
00058
00059 LocatableException::~LocatableException() throw()
00060 {
00061
00062 }
00063
00064
00065
00066
00067 ReferentialChangedEvent::ReferentialChangedEvent( EventSource & source ) :
00068 Event( source )
00069 {
00070
00071 }
00072
00073
00074
00075 ReferentialChangedEvent::~ReferentialChangedEvent() throw()
00076 {
00077
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087 Locatable::Locatable( Locatable & fatherLocatable ) :
00088 EventSource(),
00089 EventListener(),
00090 _father( & fatherLocatable ),
00091 _localReferential( 0 ),
00092 _globalReferential( 0 ),
00093 _changedEvent( 0 ),
00094 _isUpToDate( false )
00095 {
00096
00097
00098
00099
00100
00101
00102
00103
00104 try
00105 {
00106
00107 subscribeTo( * _father ) ;
00108
00109 }
00110 catch( const EventException & e )
00111 {
00112
00113 LogPlug::error( "Locatable constructor: " + e.toString() ) ;
00114
00115 }
00116
00117 }
00118
00119
00120
00121 Locatable::Locatable() :
00122 _father( 0 ),
00123 _localReferential( 0 ),
00124 _globalReferential( 0 ),
00125 _changedEvent( 0 ),
00126 _isUpToDate( false )
00127 {
00128
00129 }
00130
00131
00132
00133 Locatable::Locatable( Locatable & fatherLocatable, Matrix & localReferential ) :
00134 _father( & fatherLocatable ),
00135 _localReferential( & localReferential ),
00136 _globalReferential( 0 ),
00137 _changedEvent( 0 ),
00138 _isUpToDate( false )
00139 {
00140
00141
00142
00143
00144
00145
00146
00147 try
00148 {
00149
00150 subscribeTo( * _father ) ;
00151
00152 }
00153 catch( const EventException & e )
00154 {
00155
00156 LogPlug::error( "Locatable constructor failed: " + e.toString() ) ;
00157
00158 }
00159
00160 }
00161
00162
00163
00164 Locatable::Locatable( Matrix & localReferential ) :
00165 _father( 0 ),
00166 _localReferential( & localReferential ),
00167 _globalReferential( 0 ),
00168 _changedEvent( 0 ),
00169 _isUpToDate( false )
00170 {
00171
00172 }
00173
00174
00175
00176 Locatable::~Locatable() throw()
00177 {
00178
00179 if ( _father != 0 )
00180 {
00181
00182 try
00183 {
00184 detachFromFather() ;
00185
00186
00187
00188 }
00189 catch( const LocatableException & e )
00190 {
00191 LogPlug::error( "Locatable destructor: " + e.toString() ) ;
00192 }
00193
00194 }
00195
00196
00197 removeAllListeners() ;
00198
00199
00200 if ( _localReferential != 0 )
00201 delete _localReferential ;
00202
00203 if ( _globalReferential != 0 )
00204 delete _globalReferential ;
00205
00206 if ( _changedEvent != 0 )
00207 delete _changedEvent ;
00208
00209 }
00210
00211
00212
00213 bool Locatable::isAbsolute() const
00214 {
00215
00216 return ( _father == 0 ) ;
00217
00218 }
00219
00220
00221
00222 bool Locatable::hasLocalReferential() const
00223 {
00224
00225 return ( _localReferential != 0 ) ;
00226
00227 }
00228
00229
00230
00231 Matrix & Locatable::getLocalReferential() const
00232 {
00233
00234 if ( _localReferential == 0 )
00235 throw LocatableException( "Locatable::getLocalReferential(): "
00236 "no local referential available." ) ;
00237
00238 return * _localReferential ;
00239
00240 }
00241
00242
00243
00244 void Locatable::setLocalReferential( Matrix & newGlobalReferential )
00245 {
00246
00247 _localReferential = & newGlobalReferential ;
00248
00249 }
00250
00251
00252
00253 bool Locatable::hasGlobalReferential() const
00254 {
00255
00256 return _globalReferential != 0 ;
00257
00258 }
00259
00260
00261
00262 Matrix & Locatable::getGlobalReferential()
00263 {
00264
00265 if ( _isUpToDate )
00266 {
00267
00268 #if CEYLAN_DEBUG
00269
00270 if ( _globalReferential == 0 )
00271 emergencyShutdown( "Locatable::getGlobalReferential(): "
00272 "Locatable should be up-to-date, "
00273 "whereas no global referential available." ) ;
00274
00275 #endif // CEYLAN_DEBUG
00276
00277 return * _globalReferential ;
00278
00279 }
00280
00281 if ( isAbsolute() )
00282 {
00283
00284 if ( _localReferential == 0 )
00285 throw LocatableException( "Locatable::getGlobalReferential(): "
00286 "this absolute referential has no "
00287 "local referential available." ) ;
00288
00289 return * _localReferential ;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299 if ( _globalReferential != 0 )
00300 {
00301 delete _globalReferential ;
00302 _globalReferential = 0 ;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 updateFromFather( _father->getGlobalReferential() ) ;
00314
00315
00316 setUpToDateState( true ) ;
00317
00318 return * _globalReferential ;
00319
00320 }
00321
00322
00323
00324 bool Locatable::isUpToDate() const
00325 {
00326
00327 return _isUpToDate ;
00328
00329 }
00330
00331
00332
00333 void Locatable::setUpToDateState( bool newState )
00334 {
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 if ( ( newState == false ) && ( _isUpToDate == true ) )
00346 {
00347
00348
00349
00350
00351
00352 changed() ;
00353 }
00354
00355 _isUpToDate = newState ;
00356
00357 }
00358
00359
00360
00361 void Locatable::beNotifiedOf( const Event & newEvent )
00362 {
00363
00364 if ( dynamic_cast<const ReferentialChangedEvent *>( & newEvent ) != 0 )
00365 setUpToDateState( false ) ;
00366
00367
00368
00369 }
00370
00371
00372
00373 const string Locatable::toString( VerbosityLevels level ) const
00374 {
00375
00376 string res ;
00377
00378 if ( isAbsolute() )
00379 res = "Absolute" ;
00380 else
00381 res = "Relative" ;
00382
00383 return res + " Locatable, " + describe( level ) ;
00384
00385 }
00386
00387
00388
00389 void Locatable::changed()
00390 {
00391
00392
00393 if ( _globalReferential != 0 )
00394 {
00395 delete _globalReferential ;
00396 _globalReferential = 0 ;
00397 }
00398
00399 if ( _changedEvent == 0 )
00400 _changedEvent = new ReferentialChangedEvent( * this ) ;
00401
00402 notifyAllListeners( * _changedEvent ) ;
00403
00404 }
00405
00406
00407
00408 void Locatable::detachFromFather()
00409 {
00410
00411 if ( _father == 0 )
00412 throw LocatableException(
00413 "Locatable::detachFromFather: no father registered." ) ;
00414
00415 try
00416 {
00417 unsubscribeFrom( *_father ) ;
00418 }
00419 catch( const EventException & e )
00420 {
00421
00422 LogPlug::error( "Locatable::detachFromFather failed: "
00423 + e.toString() ) ;
00424 }
00425
00426 }
00427
00428
00429
00430 const string Locatable::describe( VerbosityLevels level ) const
00431 {
00432
00433 string res ;
00434
00435 if ( _localReferential == 0 )
00436 {
00437 res += "no local referential available" ;
00438 }
00439 else
00440 {
00441 res += "local referential available" ;
00442 if ( level == Ceylan::high )
00443 res += " (" + _localReferential->toString( level ) + " )" ;
00444 }
00445
00446 if ( _globalReferential == 0 )
00447 {
00448 res += ", no global referential available" ;
00449 }
00450 else
00451 {
00452 res += ", global referential available" ;
00453 if ( level == Ceylan::high )
00454 res += " (" + _globalReferential->toString( level ) + " )" ;
00455 }
00456
00457 res += ". " ;
00458
00459 ListSize listenersCount = _listeners.size() ;
00460
00461 if ( listenersCount > 0 )
00462 {
00463 if ( listenersCount == 1 )
00464 res += "There is exactly one referential "
00465 "that is directly relative to this Locatable" ;
00466 else
00467 res += "There are "
00468 + Ceylan::toString(
00469 static_cast<Ceylan::Uint32>( listenersCount ) )
00470 + " referentials which are directly relative "
00471 "to this Locatable" ;
00472 }
00473 else
00474 res += " No Locatable depends on this one" ;
00475
00476 return res ;
00477
00478 }
00479