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 #ifndef SO_SUB_FIELDCONTAINER_H
00026 #define SO_SUB_FIELDCONTAINER_H
00027
00028 #include <Inventor/threads/SbThreadMutex.h>
00029 #include <Inventor/fields/SoFieldData.h>
00030
00032
00033
00034
00035 #define SO_FIELDCONTAINER_ABSTRACT_HEADER(className) \
00036 public: \
00037 \
00038 static SoType getClassTypeId(); \
00039 \
00040 virtual SoType getTypeId() const; \
00041 private: \
00042 virtual SbBool getIsBuiltIn() const ; \
00043 virtual const SoFieldData* getFieldData() const; \
00044 static void initClass(); \
00045 static void exitClass(); \
00046 private: \
00047 static const SoFieldData** getFieldDataPtr(); \
00048 private: \
00049 static SbThreadMutex classMutex; \
00050 static SoType classTypeId; \
00051 static SbBool isBuiltIn; \
00052 static SbBool firstInstance; \
00053 static SoFieldData* fieldData; \
00054 static const SoFieldData** parentFieldData
00055
00057
00058
00059
00060 #define SO_FIELDCONTAINER_HEADER(className) \
00061 SO_FIELDCONTAINER_ABSTRACT_HEADER(className); \
00062 private: \
00063 static void* createInstance(SoType* dynamicType = NULL)
00064
00065 #if defined(_DEBUG)
00066
00068 #define SO__FIELDCONTAINER_CHECK_INIT(className) \
00069 if (classTypeId.isBad()) \
00070 { \
00071 SoDebugError::post( \
00072 "SO_FIELDCONTAINER_CONSTRUCTOR", \
00073 "Can't construct a node of type " \
00074 SO__QUOTE(className) \
00075 " until initClass() has been called"); \
00076 className::initClass(); \
00077 } \
00078 SoTypedObject::checkDatabase(SO__QUOTE(className), this, className::getClassTypeId(), classTypeId);
00079
00081 #define SO__FIELDCONTAINER_CHECK_CONSTRUCT(where) \
00082 if (fieldData == NULL) \
00083 { \
00084 SoDebugError::post( \
00085 where, \
00086 "Instance not properly constructed.\n" \
00087 "Did you forget to put SO_FIELDCONTAINER_CONSTRUCTOR()" \
00088 " in the constructor?" ); \
00089 fieldData = new SoFieldData( \
00090 parentFieldData ? *parentFieldData : NULL); \
00091 }
00092
00093 #else
00094
00096 #define SO__FIELDCONTAINER_CHECK_INIT(className) \
00097 if (classTypeId.isBad()) \
00098 className::initClass()
00099
00101 #define SO__FIELDCONTAINER_CHECK_CONSTRUCT(where) \
00102 if (fieldData == NULL) \
00103 fieldData = new SoFieldData( \
00104 parentFieldData ? *parentFieldData : NULL)
00105
00106 #endif
00107
00109
00110
00111
00112 #define SO__FIELDCONTAINER_VARS(className) \
00113 SbThreadMutex className::classMutex; \
00114 SoType className::classTypeId; \
00115 SbBool className::isBuiltIn = TRUE; \
00116 SoFieldData* className::fieldData = NULL; \
00117 const SoFieldData** className::parentFieldData = NULL; \
00118 SbBool className::firstInstance = TRUE
00119
00121 #define SO_FIELDCONTAINER_ABSTRACT_SOURCE(className) \
00122 SO__FIELDCONTAINER_VARS(className); \
00123 SoType className::getTypeId() const \
00124 { \
00125 return classTypeId; \
00126 } \
00127 \
00128 const SoFieldData* className::getFieldData() const \
00129 { \
00130 classMutex.lock(); \
00131 SO__FIELDCONTAINER_CHECK_CONSTRUCT(SO__QUOTE(className)); \
00132 SoFieldData* result = fieldData; \
00133 classMutex.unlock(); \
00134 return result; \
00135 } \
00136 \
00137 SoType className::getClassTypeId() \
00138 { \
00139 return classTypeId; \
00140 } \
00141 \
00142 SbBool className::getIsBuiltIn() const \
00143 { \
00144 return isBuiltIn; \
00145 } \
00146 \
00147 const SoFieldData** className::getFieldDataPtr() \
00148 { \
00149 classMutex.lock(); \
00150 const SoFieldData** result = (const SoFieldData**)&fieldData; \
00151 classMutex.unlock(); \
00152 return result; \
00153 }
00154
00156 #define SO_FIELDCONTAINER_SOURCE(className) \
00157 SO_FIELDCONTAINER_ABSTRACT_SOURCE(className); \
00158 \
00159 void* className::createInstance(SoType* ) \
00160 { \
00161 return (void *)(new className); \
00162 }
00163
00164 #if defined(_DEBUG)
00165 #define SO_FIELDCONTAINER_INIT_CLASS_CHECK_PARENT(className, parentClass) \
00166 if (parentClass::getClassTypeId().isBad()) { \
00167 SoDebugError::post( SO__QUOTE(className)"::initClass", \
00168 SO__QUOTE(className)" initialized before parent class " \
00169 SO__QUOTE(parentClass)"\n"); \
00170 parentClass::initClass(); \
00171 }
00172 #else
00173 #define SO_FIELDCONTAINER_INIT_CLASS_CHECK_PARENT(className, parentClass) \
00174 if (parentClass::getClassTypeId().isBad()) \
00175 parentClass::initClass()
00176 #endif
00177
00179
00180
00181
00182
00183
00184 #define SO_FIELDCONTAINER_INIT_CLASS(className, classPrintName, parentClass) \
00185 classMutex.lock(); \
00186 SO_FIELDCONTAINER_INIT_CLASS_CHECK_PARENT(className, parentClass); \
00187 classTypeId = SoType::createType( parentClass::getClassTypeId(), \
00188 classPrintName, \
00189 &className::createInstance, 0 ); \
00190 parentFieldData = parentClass::getFieldDataPtr(); \
00191 classMutex.unlock()
00192
00194 #define SO_FIELDCONTAINER_INIT_ABSTRACT_CLASS(className, classPrintName, parentClass) \
00195 classMutex.lock(); \
00196 SO_FIELDCONTAINER_INIT_CLASS_CHECK_PARENT(className, parentClass); \
00197 classTypeId = SoType::createType( parentClass::getClassTypeId(), \
00198 classPrintName, \
00199 NULL, 0 ); \
00200 parentFieldData = parentClass::getFieldDataPtr(); \
00201 classMutex.unlock()
00202
00203 #if defined(_DEBUG)
00204 #define SO__FIELDCONTAINER_EXIT_CLASS(className) \
00205 if (! SoType::removeType(classTypeId.getName())) { \
00206 SoDebugError::post(SO__QUOTE(className)"::exitClass", \
00207 "Unable to remove type (%s) for this class. Check exitClass() " \
00208 "method is implemented and is called only once.\n", \
00209 classTypeId.getName().getString() ); \
00210 } \
00211 else \
00212 { \
00213 classTypeId = SoType::badType(); \
00214 firstInstance = TRUE; \
00215 if (fieldData != NULL) \
00216 { \
00217 delete fieldData; \
00218 fieldData = NULL; \
00219 } \
00220 parentFieldData = NULL; \
00221 firstInstance = TRUE; \
00222 }
00223 #else
00224 #define SO__FIELDCONTAINER_EXIT_CLASS(className) \
00225 SoType::removeType(classTypeId.getName()); \
00226 classTypeId = SoType::badType(); \
00227 firstInstance = TRUE; \
00228 if (fieldData != NULL) \
00229 { \
00230 delete fieldData; \
00231 fieldData = NULL; \
00232 } \
00233 parentFieldData = NULL; \
00234 firstInstance = TRUE
00235 #endif
00236
00238
00239
00240
00241 #define SO_FIELDCONTAINER_IS_FIRST_INSTANCE() \
00242 (firstInstance == TRUE)
00243
00245 #define SO__FIELDCONTAINER_ADD_MFIELD( fieldName, type ) \
00246 classMutex.lock(); \
00247 SO__FIELDCONTAINER_CHECK_CONSTRUCT(__FILE__); \
00248 if (firstInstance) \
00249 fieldData->addField(this, SO__QUOTE(fieldName), &this->fieldName); \
00250 this->fieldName.setContainer(this); \
00251 this->fieldName.setFieldType(type); \
00252 classMutex.unlock()
00253
00255 #define SO__FIELDCONTAINER_ADD_FIELD( fieldName, defValue, type ) \
00256 classMutex.lock(); \
00257 SO__FIELDCONTAINER_CHECK_CONSTRUCT(__FILE__); \
00258 if (firstInstance) \
00259 fieldData->addField(this, SO__QUOTE(fieldName), &this->fieldName); \
00260 this->fieldName.setValue defValue; \
00261 this->fieldName.setContainer(this); \
00262 this->fieldName.setFieldType(type); \
00263 classMutex.unlock()
00264
00266 #define SO_FIELDCONTAINER_ADD_FIELD( fieldName, defValue ) \
00267 SO__FIELDCONTAINER_ADD_FIELD( fieldName, defValue, SoField::EXPOSED_FIELD )
00268
00270 #define SO_FIELDCONTAINER_ADD_HIDDEN_FIELD( fieldName, defValue ) \
00271 SO__FIELDCONTAINER_ADD_FIELD( fieldName, defValue, SoField::INTERNAL_FIELD )
00272
00274 #define SO_FIELDCONTAINER_ADD_PRIVATEFIELD( fieldName, defValue ) \
00275 SO__FIELDCONTAINER_ADD_FIELD( fieldName, defValue, SoField::HIDDEN_FIELD )
00276
00278 #define SO_FIELDCONTAINER_SET_SF_ENUM_TYPE( fieldName, enumType ) \
00279 SO__SF_ENUM_SET_TYPE( fieldName, enumType, "FIELDCONTAINER", fieldData )
00280
00282 #define SO_FIELDCONTAINER_CONSTRUCTOR(className) \
00283 SoBaseInitializer sbi(this); \
00284 classMutex.lock(); \
00285 SO__FIELDCONTAINER_CHECK_INIT(className); \
00286 if (fieldData == NULL) \
00287 fieldData = new SoFieldData( parentFieldData ? \
00288 (SoFieldData *)*parentFieldData : \
00289 (SoFieldData *)NULL); \
00290 else \
00291 firstInstance = FALSE; \
00292 classMutex.unlock()
00293
00295 #define SO__FIELDCONTAINER_DEFINE_ENUM_VALUE( enumType, enumValueName, enumValue ) \
00296 classMutex.lock(); \
00297 if (firstInstance) \
00298 fieldData->addEnumValue(SO__QUOTE(enumType), \
00299 SO__QUOTE(enumValueName), \
00300 enumValue); \
00301 classMutex.unlock()
00302
00304 #define SO_FIELDCONTAINER_DEFINE_ENUM_VALUE( enumType, enumValue ) \
00305 SO__FIELDCONTAINER_DEFINE_ENUM_VALUE( enumType, enumValue, enumValue )
00306
00307 #endif // SO_SUB_FIELDCONTAINER_H
00308
00309
00310
00311
00312