00001 #include "AbstractPropertyContainer.h"
00002 #include "PropertyContainerEvent.h"
00003 #include "Property.h"
00004 #include "XMLNode.h"
00005
00006 namespace RenderTools {
00007
00008 map< string, string > AbstractPropertyContainer::s_variables;
00009
00010 AbstractPropertyContainer::AbstractPropertyContainer( void ):
00011 ContainerProperty(){
00012 }
00013
00014 AbstractPropertyContainer::~AbstractPropertyContainer( void ){
00015 }
00016
00017 void AbstractPropertyContainer::createProperties( void ){
00018 }
00019
00021 void AbstractPropertyContainer::initialize( bool force ){
00022 if( ! isInitialized() || force ){
00023 onInitialize();
00024 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00025 m_properties[ i ]->initialize( force );
00026 }
00027 setInitialized( true );
00028 }
00029 }
00030
00031 void AbstractPropertyContainer::onInitialize( void ){
00032
00033 }
00034
00035 void AbstractPropertyContainer::setName( const string name ){
00036 AbstractProperty::setName( name );
00037 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00038 m_properties[ i ]->recalculatePath();
00039 }
00040 }
00041
00042 void AbstractPropertyContainer::setName( const XMLNodePtr & xml ){
00043 AbstractProperty::setName( xml );
00044 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00045 m_properties[ i ]->recalculatePath();
00046 }
00047 }
00048
00049 void AbstractPropertyContainer::recalculatePath( void ){
00050 AbstractProperty::recalculatePath();
00051 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00052 m_properties[ i ]->recalculatePath();
00053 }
00054 }
00055
00056 void AbstractPropertyContainer::setOwner( const PropertyContainerPtr & owner ){
00057 AbstractProperty::setOwner( owner );
00058 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00059 m_properties[ i ]->recalculatePath();
00060 }
00061 }
00062
00063 const PropertyPtr AbstractPropertyContainer::addProperty( const string name, bool send ){
00064 PropertyPtr p( new AbstractProperty() );
00065 p->setName( name );
00066 addProperty( p, send );
00067 return( p );
00068 }
00069
00070 void AbstractPropertyContainer::onPropertyEvent( const PropertyEvent & p ){
00071 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00072 m_properties[ i ]->onPropertyEvent( p );
00073 }
00074 }
00075
00076 void AbstractPropertyContainer::onPropertyContainerEvent( const PropertyContainerEvent & e ){
00077
00078 }
00079
00080 void AbstractPropertyContainer::sendPropertyContainerEvent( const PropertyContainerEvent & e ){
00081 onPropertyContainerEvent( e );
00082 }
00083
00084 const string AbstractPropertyContainer::interpret( const string value ){
00085 string result = value;
00086 map< string, string >::iterator i;
00087
00089 i = s_variables.begin();
00090 for( ; i != s_variables.end(); i++ ){
00091 replace( result, i->first, i->second );
00092 }
00093
00094 return( result );
00095 }
00096
00098 void AbstractPropertyContainer::extractVariables( const XMLNodePtr & xml ){
00099 if( xml ){
00100 if( xml->getTagName() == "variable" ){
00101 addVariable( xml->getAttrib<string>( "name" ), xml->getAttrib<string>( "value" ) );
00102 }
00103 XMLNodePtr child = XMLNodePtr();
00104 while( ( child = ( XMLNodePtr )xml->nextChild( ( const XMLNodePtr )child ) ) ){
00105 extractVariables( child );
00106 }
00107 }
00108 }
00109
00110 void AbstractPropertyContainer::addVariable( const string key, const string value ){
00111 s_variables[ key ] = value;
00112 }
00113
00114 const PropertyList & AbstractPropertyContainer::getProperties( void ) const{
00115 return( m_properties );
00116 }
00117
00118 const PropertyPtr AbstractPropertyContainer::getProperty( const string name ) const {
00119 string local = name;
00120 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00121 if( m_properties[ i ]->getName() == name ){
00122 return( m_properties[ i ] );
00123 }
00124 }
00125 return( PropertyPtr() );
00126 }
00127
00128 const PropertyPtr AbstractPropertyContainer::getItem( unsigned int i ) const {
00129 return( getProperty( i ) );
00130 }
00131
00132 const PropertyPtr AbstractPropertyContainer::getProperty( unsigned int i ) const {
00133 if( i >= m_properties.size() ){
00134 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00135 return( PropertyPtr() );
00136 }
00137 return( m_properties[ i ] );
00138 }
00139
00140 void AbstractPropertyContainer::setProperty( const string name, const string value, bool send ){
00141 PropertyPtr p = getProperty( name );
00142 if( p ){
00143 if( p->setValue( value ) && send ){
00144 sendPropertyEvent( PropertyEvent( PropertyEvent::CHANGED, p ) );
00145 }
00146 }
00147 }
00148
00149 void AbstractPropertyContainer::setProperty( const XMLNodePtr & xml, bool send ){
00150 if( xml ){
00152 if( xml->getTagName() == "variable" ){
00154 AbstractPropertyContainer::addVariable( xml->getAttrib<string>( "name" ), xml->getAttrib<string>( "value" ) );
00155 }
00156 else{
00158 PropertyPtr p = findProperty( xml->getTagName() );
00159 if( ! p ){
00161 if( Factory::isRegisteredClass( xml->getAttrib<string>( "type" ) ) ){
00163 if( ! xml->hasChildren() ){
00165 p = addProperty( xml->getTagName(), send );
00166 }
00167 else{
00169 p = addProperty( Factory::create( xml ), send );
00170 }
00171 }
00172
00173
00174
00175
00177
00179
00180
00181
00183
00184
00185
00186
00187 }
00188 if( p ){
00189 if( p->isContainer() ){
00191 PropertyContainerPtr pc = dynamic_pointer_cast< AbstractPropertyContainer, AbstractProperty >( p );
00192 pc->setProperties( xml, send );
00193 }
00194 else if( p->setValue( xml->getAttrib<string>( "value" ) ) && send ){
00196 sendPropertyEvent( PropertyEvent( PropertyEvent::CHANGED, p ) );
00197 }
00198 }
00199 else{
00200 Error::warning( Error::PROPERTY_DOES_NOT_EXIST, __FILE__, __LINE__ );
00201 }
00202 }
00203 }
00204 }
00205
00206 void AbstractPropertyContainer::setProperties( const XMLNodePtr & xml, bool send ){
00207 if( xml ){
00208 setName( xml );
00209 XMLNodePtr child = XMLNodePtr();
00210 while( ( child = xml->nextChild( child ) ) ){
00211 setProperty( child, send );
00212 }
00213 }
00214 }
00215
00216 bool AbstractPropertyContainer::isProperty( const PropertyPtr & p ) const {
00217 if( ! p ){
00218 Error::error( Error::NULL_POINTER, __FILE__, __LINE__ );
00219 }
00220 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00221 if( m_properties[ i ] == p ){
00222 return( true );
00223 }
00224 }
00225 return( false );
00226 }
00227
00228 bool AbstractPropertyContainer::isProperty( const string name ) const {
00229 string cleanName = name;
00230 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00231 if( m_properties[ i ]->getName() == cleanName ){
00232 return( true );
00233 }
00234 }
00235 return( false );
00236 }
00237
00238 bool AbstractPropertyContainer::isProperty( const string name, const string value ) const {
00239 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00240 if( m_properties[ i ]->getName() == name && m_properties[ i ]->getValue( ) == value ){
00241 return( true );
00242 }
00243 }
00244 return( false );
00245 }
00246
00247 bool AbstractPropertyContainer::removeProperty( unsigned int index, bool send ){
00248 if( index < 0 || index >= m_properties.size() ){
00249 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00250 }
00251 PropertyPtr p = m_properties[ index ];
00252 p->setOwner( PropertyContainerPtr() );
00253 m_properties[ index ] = m_properties[ m_properties.size() - 1 ];
00254 m_properties.pop_back();
00255 if( send ){
00256 sendPropertyEvent( PropertyEvent( PropertyEvent::CHANGED, getSharedPtr< AbstractProperty >() ) );
00257 }
00258 return( false );
00259 }
00260
00261 bool AbstractPropertyContainer::removeProperty( const PropertyPtr & p, bool send ){
00262 if( ! p ){
00263 Error::error( Error::NULL_POINTER, __FILE__, __LINE__ );
00264 }
00265 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00266 if( m_properties[ i ] == p ){
00267 return( removeProperty( i, send ) );
00268 }
00269 }
00270 return( false );
00271 }
00272
00273 bool AbstractPropertyContainer::removeProperties( bool send ){
00274 return( removeProperties( 0, m_properties.size(), send ) );
00275 }
00276
00277 bool AbstractPropertyContainer::removeProperties( unsigned int first, unsigned int last, bool send ){
00278 if( m_properties.size() == 0 || first >= m_properties.size() ){
00279 return( false );
00280 }
00281 if( last >= m_properties.size() ){
00282 last = ( ( int )m_properties.size() ) - 1;
00283 }
00284
00286 PropertyList properties;
00287 for( unsigned int i = first; i <= last; i++ ){
00288 properties.push_back( m_properties[ i ] );
00289 }
00291 for( unsigned int i = 0; i < properties.size(); i++ ){
00292 removeProperty( properties[ i ], send );
00293 }
00294 return( properties.size() > 0 );
00295 }
00296
00297 const PropertyPtr AbstractPropertyContainer::addProperty( const PropertyPtr & p, bool send ){
00298 if( ! p ){
00299 Error::error( Error::NULL_POINTER, __FILE__, __LINE__ );
00300 }
00301 if( isProperty( p->getName() ) ){
00302 Error::warning( Error::ITEM_ALREADY_EXISTS, __FILE__, __LINE__ );
00303 }
00304 else{
00305 m_properties.push_back( p );
00306 const_pointer_cast< AbstractProperty >( p )->setOwner( getSharedPtr< AbstractPropertyContainer >() );
00307 if( send ){
00308 sendPropertyContainerEvent( PropertyContainerEvent( PropertyContainerEvent::ADD_PROPERTY, getSharedPtr< AbstractPropertyContainer >(), p->getName() ) );
00309 }
00310 }
00311 return( p );
00312 }
00313
00314 void AbstractPropertyContainer::findPointers( const string name, PropertyList & results ){
00315 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00316 if( m_properties[ i ]->getName() == name || name == "" ){
00317 results.push_back( m_properties[ i ] );
00318 }
00319 }
00320 }
00321
00322 const PropertyPtr AbstractPropertyContainer::findProperty( const void * pointer ) const {
00323 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00324 if( m_properties[ i ]->getPointer( 0 ) == pointer ){
00325 return( m_properties[ i ] );
00326 }
00327 }
00328 return( PropertyPtr() );
00329 }
00330
00331
00332 const PropertyPtr AbstractPropertyContainer::findProperty( const string name ) const {
00334 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00335 if( m_properties[ i ]->getName() == name ){
00336 return( m_properties[ i ] );
00337 }
00338 }
00339
00340 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00341 if( m_properties[ i ]->isContainer() ){
00342 const PropertyContainerPtr pc = dynamic_pointer_cast< AbstractPropertyContainer, AbstractProperty >( m_properties[ i ] );
00343 const PropertyPtr ptr = pc->findProperty( name );
00344 if( ptr ){
00345 return( ptr );
00346 }
00347 }
00348 }
00349 return( PropertyPtr() );
00350 }
00351
00352 int AbstractPropertyContainer::findIndex( const string name ) const {
00354 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00355 if( m_properties[ i ]->getName() == name ){
00356 return( i );
00357 }
00358 }
00359
00360 for( unsigned int i = 0; i < m_properties.size(); i++ ){
00361 if( m_properties[ i ]->isContainer() ){
00362 const PropertyContainerPtr pc = dynamic_pointer_cast< AbstractPropertyContainer, AbstractProperty >( m_properties[ i ] );
00363 const PropertyPtr ptr = pc->findProperty( name );
00364 if( ptr ){
00365 return( i );
00366 }
00367 }
00368 }
00369 return( -1 );
00370 }
00371
00372 const XMLNodePtr AbstractPropertyContainer::toXML( const XMLNodePtr & parent ) const {
00373
00375 bool expand = ( ! parent ) || ( ! parent->findByFullName( m_name, getTypeName() ) );
00376
00377 XMLNodePtr xml( new XMLNode( m_name ) );
00378 if( parent ){
00379 parent->addChild( xml );
00380 }
00381 xml->setAttrib<string>( "type", getTypeName() );
00383 if( expand ){
00384 for( unsigned i = 0; i < m_properties.size(); i++ ){
00385 m_properties[ i ]->toXML( xml );
00386 }
00387 }
00388 return( xml );
00389 }
00390
00392 void AbstractPropertyContainer::addPropertyToOwner( AbstractPropertyContainer * owner, const PropertyPtr p ){
00393 if( owner ){
00394 owner->addProperty( p, true );
00395 }
00396 }
00397
00398 void AbstractPropertyContainer::removePropertyFromOwner( AbstractPropertyContainer * owner, const PropertyPtr p ){
00399 if( owner ){
00400 owner->removeProperty( p, true );
00401 }
00402 }
00403
00404 unsigned int AbstractPropertyContainer::size( void ) const{
00405 return( m_properties.size() );
00406 }
00407
00408 const PropertyPtr AbstractPropertyContainer::operator [] ( int index ) const {
00409 if( index < 0 || index >= (int)m_properties.size() ){
00410 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00411 }
00412 return( m_properties[ index ] );
00413 }
00414
00415 PropertyPtr AbstractPropertyContainer::operator [] ( int index ){
00416 if( index < 0 || index >= (int)m_properties.size() ){
00417 Error::error( Error::INDEX_OUT_OF_BOUNDS, __FILE__, __LINE__ );
00418 }
00419 return( m_properties[ index ] );
00420 }
00421
00422 ostream & operator << ( ostream & os, const AbstractPropertyContainer & rhs ){
00423 os << rhs.getName() << endl;
00424 for( unsigned int i = 0; i < rhs.getProperties().size(); i++ ){
00425 os << "\t" << * rhs[ i ] << endl;
00426 }
00427 return( os );
00428 }
00429
00430 const istream & operator >> ( const istream & is, AbstractPropertyContainer & rhs ){
00431 return( is );
00432 }
00433
00434
00435 };
00436