Open Inventor Release 2024.2.1
 
Loading...
Searching...
No Matches
SoSubFieldContainer.h
1/*=======================================================================
2 *** THE CONTENT OF THIS WORK IS PROPRIETARY TO FEI S.A.S, (FEI S.A.S.), ***
3 *** AND IS DISTRIBUTED UNDER A LICENSE AGREEMENT. ***
4 *** ***
5 *** REPRODUCTION, DISCLOSURE, OR USE, IN WHOLE OR IN PART, OTHER THAN AS ***
6 *** SPECIFIED IN THE LICENSE ARE NOT TO BE UNDERTAKEN EXCEPT WITH PRIOR ***
7 *** WRITTEN AUTHORIZATION OF FEI S.A.S. ***
8 *** ***
9 *** RESTRICTED RIGHTS LEGEND ***
10 *** USE, DUPLICATION, OR DISCLOSURE BY THE GOVERNMENT OF THE CONTENT OF THIS ***
11 *** WORK OR RELATED DOCUMENTATION IS SUBJECT TO RESTRICTIONS AS SET FORTH IN ***
12 *** SUBPARAGRAPH (C)(1) OF THE COMMERCIAL COMPUTER SOFTWARE RESTRICTED RIGHT ***
13 *** CLAUSE AT FAR 52.227-19 OR SUBPARAGRAPH (C)(1)(II) OF THE RIGHTS IN ***
14 *** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 52.227-7013. ***
15 *** ***
16 *** COPYRIGHT (C) 1996-2014 BY FEI S.A.S, ***
17 *** BORDEAUX, FRANCE ***
18 *** ALL RIGHTS RESERVED ***
19**=======================================================================*/
20/*=======================================================================
21** Author : Nicolas DAGUISE (Aug 2007)
22**=======================================================================*/
23
24
25#ifndef SO_SUB_FIELDCONTAINER_H
26#define SO_SUB_FIELDCONTAINER_H
27
28#include <Inventor/threads/SbThreadMutex.h>
29#include <Inventor/fields/SoFieldData.h>
30
32// These defines type-identifier and naming variables and methods that
33// all subclasses and abstract subclasses must support.
34//
35#define SO_FIELDCONTAINER_ABSTRACT_HEADER(className) \
36 public: \
37 \
38 static SoType getClassTypeId(); \
39 \
40 virtual SoType getTypeId() const; \
41 private: \
42 virtual SbBool getIsBuiltIn() const ; \
43 virtual const SoFieldData* getFieldData() const; \
44 static void initClass(); \
45 static void exitClass(); \
46 private: \
47 static const SoFieldData** getFieldDataPtr(); \
48 private: \
49 static SbThreadMutex classMutex; \
50 static SoType classTypeId; \
51 static SbBool isBuiltIn; \
52 static SbBool firstInstance; \
53 static SoFieldData* fieldData; \
54 static const SoFieldData** parentFieldData
55
57// Non-abstract classes have everything abstract classes have, plus a way
58// to create an instance
59//
60#define SO_FIELDCONTAINER_HEADER(className) \
61 SO_FIELDCONTAINER_ABSTRACT_HEADER(className); \
62private: \
63 static void* createInstance(SoType* dynamicType = NULL)
64
65#if defined(_DEBUG)
66
68#define SO__FIELDCONTAINER_CHECK_INIT(className) \
69 if (classTypeId.isBad()) \
70 { \
71 SoDebugError::post( \
72 "SO_FIELDCONTAINER_CONSTRUCTOR", \
73 "Can't construct a node of type " \
74 SO__QUOTE(className) \
75 " until initClass() has been called"); \
76 className::initClass(); \
77 } \
78 SoTypedObject::checkDatabase(SO__QUOTE(className), this, className::getClassTypeId(), classTypeId);
79
81#define SO__FIELDCONTAINER_CHECK_CONSTRUCT(where) \
82 if (fieldData == NULL) \
83 { \
84 SoDebugError::post( \
85 where, \
86 "Instance not properly constructed.\n" \
87 "Did you forget to put SO_FIELDCONTAINER_CONSTRUCTOR()" \
88 " in the constructor?" ); \
89 fieldData = new SoFieldData( \
90 parentFieldData ? *parentFieldData : NULL); \
91 }
92
93#else
94
96#define SO__FIELDCONTAINER_CHECK_INIT(className) \
97 if (classTypeId.isBad()) \
98 className::initClass()
99
101#define SO__FIELDCONTAINER_CHECK_CONSTRUCT(where) \
102 if (fieldData == NULL) \
103 fieldData = new SoFieldData( \
104 parentFieldData ? *parentFieldData : NULL)
105
106#endif
107
109// This declares the static variables defined in SO_FIELDCONTAINER_HEADER
110// or SO_FIELDCONTAINER_ABSTRACT_HEADER.
111//
112#define SO__FIELDCONTAINER_VARS(className) \
113 SbThreadMutex className::classMutex; \
114 SoType className::classTypeId; \
115 SbBool className::isBuiltIn = TRUE; \
116 SoFieldData* className::fieldData = NULL; \
117 const SoFieldData** className::parentFieldData = NULL; \
118 SbBool className::firstInstance = TRUE
119
121#define SO_FIELDCONTAINER_ABSTRACT_SOURCE(className) \
122 SO__FIELDCONTAINER_VARS(className); \
123 SoType className::getTypeId() const \
124 { \
125 return classTypeId; \
126 } \
127 \
128 const SoFieldData* className::getFieldData() const \
129 { \
130 classMutex.lock(); \
131 SO__FIELDCONTAINER_CHECK_CONSTRUCT(SO__QUOTE(className)); \
132 SoFieldData* result = fieldData; \
133 classMutex.unlock(); \
134 return result; \
135 } \
136 \
137 SoType className::getClassTypeId() \
138 { \
139 return classTypeId; \
140 } \
141 \
142 SbBool className::getIsBuiltIn() const \
143 { \
144 return isBuiltIn; \
145 } \
146 \
147 const SoFieldData** className::getFieldDataPtr() \
148 { \
149 classMutex.lock(); \
150 const SoFieldData** result = (const SoFieldData**)&fieldData; \
151 classMutex.unlock(); \
152 return result; \
153 }
154
156#define SO_FIELDCONTAINER_SOURCE(className) \
157 SO_FIELDCONTAINER_ABSTRACT_SOURCE(className); \
158 \
159 void* className::createInstance(SoType* ) \
160 { \
161 return (void *)(new className); \
162 }
163
164#if defined(_DEBUG)
165#define SO_FIELDCONTAINER_INIT_CLASS_CHECK_PARENT(className, parentClass) \
166 if (parentClass::getClassTypeId().isBad()) { \
167 SoDebugError::post( SO__QUOTE(className)"::initClass", \
168 SO__QUOTE(className)" initialized before parent class " \
169 SO__QUOTE(parentClass)"\n"); \
170 parentClass::initClass(); \
171 }
172#else
173#define SO_FIELDCONTAINER_INIT_CLASS_CHECK_PARENT(className, parentClass) \
174 if (parentClass::getClassTypeId().isBad()) \
175 parentClass::initClass()
176#endif
177
179// This initializes the type identifer variables defined in
180// SO_FIELDCONTAINER_HEADER or SO_FIELDCONTAINER_ABSTRACT_HEADER. This macro
181// should be called from within initClass(). The parentClass argument
182// should be the class that this subclass is derived from.
183//
184#define SO_FIELDCONTAINER_INIT_CLASS(className, classPrintName, parentClass) \
185 classMutex.lock(); \
186 SO_FIELDCONTAINER_INIT_CLASS_CHECK_PARENT(className, parentClass); \
187 classTypeId = SoType::createType( parentClass::getClassTypeId(), \
188 classPrintName, \
189 &className::createInstance, 0 ); \
190 parentFieldData = parentClass::getFieldDataPtr(); \
191 classMutex.unlock()
192
194#define SO_FIELDCONTAINER_INIT_ABSTRACT_CLASS(className, classPrintName, parentClass) \
195 classMutex.lock(); \
196 SO_FIELDCONTAINER_INIT_CLASS_CHECK_PARENT(className, parentClass); \
197 classTypeId = SoType::createType( parentClass::getClassTypeId(), \
198 classPrintName, \
199 NULL, 0 ); \
200 parentFieldData = parentClass::getFieldDataPtr(); \
201 classMutex.unlock()
202
203#if defined(_DEBUG)
204#define SO__FIELDCONTAINER_EXIT_CLASS(className) \
205 if (! SoType::removeType(classTypeId.getName())) { \
206 SoDebugError::post(SO__QUOTE(className)"::exitClass", \
207 "Unable to remove type (%s) for this class. Check exitClass() " \
208 "method is implemented and is called only once.\n", \
209 classTypeId.getName().getString() ); \
210 } \
211 else \
212 { \
213 classTypeId = SoType::badType(); \
214 firstInstance = TRUE; \
215 if (fieldData != NULL) \
216 { \
217 delete fieldData; \
218 fieldData = NULL; \
219 } \
220 parentFieldData = NULL; \
221 firstInstance = TRUE; \
222 }
223#else
224#define SO__FIELDCONTAINER_EXIT_CLASS(className) \
225 SoType::removeType(classTypeId.getName()); \
226 classTypeId = SoType::badType(); \
227 firstInstance = TRUE; \
228 if (fieldData != NULL) \
229 { \
230 delete fieldData; \
231 fieldData = NULL; \
232 } \
233 parentFieldData = NULL; \
234 firstInstance = TRUE
235#endif
236
238// This is a boolean value that can be tested
239// in constructors.
240//
241#define SO_FIELDCONTAINER_IS_FIRST_INSTANCE() \
242 (firstInstance == TRUE)
243
245#define SO__FIELDCONTAINER_ADD_MFIELD( fieldName, type ) \
246 classMutex.lock(); \
247 SO__FIELDCONTAINER_CHECK_CONSTRUCT(__FILE__); \
248 if (firstInstance) \
249 fieldData->addField(this, SO__QUOTE(fieldName), &this->fieldName); \
250 this->fieldName.setContainer(this); \
251 this->fieldName.setFieldType(type); \
252 classMutex.unlock()
253
255#define SO__FIELDCONTAINER_ADD_FIELD( fieldName, defValue, type ) \
256 classMutex.lock(); \
257 SO__FIELDCONTAINER_CHECK_CONSTRUCT(__FILE__); \
258 if (firstInstance) \
259 fieldData->addField(this, SO__QUOTE(fieldName), &this->fieldName); \
260 this->fieldName.setValue defValue; \
261 this->fieldName.setContainer(this); \
262 this->fieldName.setFieldType(type); \
263 classMutex.unlock()
264
266#define SO_FIELDCONTAINER_ADD_FIELD( fieldName, defValue ) \
267 SO__FIELDCONTAINER_ADD_FIELD( fieldName, defValue, SoField::EXPOSED_FIELD )
268
270#define SO_FIELDCONTAINER_ADD_HIDDEN_FIELD( fieldName, defValue ) \
271 SO__FIELDCONTAINER_ADD_FIELD( fieldName, defValue, SoField::INTERNAL_FIELD )
272
274#define SO_FIELDCONTAINER_ADD_PRIVATEFIELD( fieldName, defValue ) \
275 SO__FIELDCONTAINER_ADD_FIELD( fieldName, defValue, SoField::HIDDEN_FIELD )
276
278#define SO_FIELDCONTAINER_SET_SF_ENUM_TYPE( fieldName, enumType ) \
279 SO__SF_ENUM_SET_TYPE( fieldName, enumType, "FIELDCONTAINER", fieldData )
280
282#define SO_FIELDCONTAINER_CONSTRUCTOR(className) \
283 SoBaseInitializer sbi(this); \
284 classMutex.lock(); \
285 SO__FIELDCONTAINER_CHECK_INIT(className); \
286 if (fieldData == NULL) \
287 fieldData = new SoFieldData( parentFieldData ? \
288 (SoFieldData *)*parentFieldData : \
289 (SoFieldData *)NULL); \
290 else \
291 firstInstance = FALSE; \
292 classMutex.unlock()
293
295#define SO__FIELDCONTAINER_DEFINE_ENUM_VALUE( enumType, enumValueName, enumValue ) \
296 classMutex.lock(); \
297 if (firstInstance) \
298 fieldData->addEnumValue(SO__QUOTE(enumType), \
299 SO__QUOTE(enumValueName), \
300 enumValue); \
301 classMutex.unlock()
302
304#define SO_FIELDCONTAINER_DEFINE_ENUM_VALUE( enumType, enumValue ) \
305 SO__FIELDCONTAINER_DEFINE_ENUM_VALUE( enumType, enumValue, enumValue )
306
307#endif // SO_SUB_FIELDCONTAINER_H
308
309
310
311