File: [Development] / inventor / lib / nodekits / src / upgraders / SoV1NkCatalog.c++ (download)
Revision 1.3, Tue Sep 25 00:45:47 2001 UTC (16 years, 1 month ago) by jlim
Branch: MAIN
CVS Tags: release-2_1_5-9, release-2_1_5-8, release-2_1_5-10, HEAD Changes since 1.2: +4 -4
lines
Various changes:
* Fixed Bug 63 and 64.
* Handled nonstandard sed location.
* Used for-loop in man page install.
* Included casts for 64-bit builds.
* Added placeholder for FreeBSD options.
* Included unistd.h for getopt() and stdlib.h for malloc().
* Implemented SoText[23] workaround for glibc-2.2.* iconv().
* Split long lines in SoHandleBoxDraggerGeom.h and
SoTransformerDraggerGeom.h in lib/interaction/src/draggers/geom.
* Added IV_NO_OVERLAYS/OIV_NO_OVERLAYS variables to disable overlay planes.
|
/*
*
* Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
*
*/
/*
* Copyright (C) 1990,91 Silicon Graphics, Inc.
*
_______________________________________________________________________
______________ S I L I C O N G R A P H I C S I N C . ____________
|
| $Revision: 1.3 $
|
| Classes:
| SoV1NodekitCatalog
|
| Author(s) : Paul Isaacs and Thad Beier
|
______________ S I L I C O N G R A P H I C S I N C . ____________
_______________________________________________________________________
*/
#include <Inventor/misc/upgraders/SoV1NodekitCatalog.h>
#include <Inventor/SoDB.h>
#include <Inventor/misc/upgraders/SoV1BaseKit.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoSwitch.h>
#include <Inventor/errors/SoDebugError.h>
// Static variables for the nodekit catalog class...
const SbName *SoV1NodekitCatalog::emptyName = NULL;
const SbPList *SoV1NodekitCatalog::emptyList = NULL;
SoType *SoV1NodekitCatalog::badType = NULL;
////////////////////////////////////////////////////////////////////////
//
// Class:
// SoV1NodekitCatalogEntry
//
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
// Description:
// Constructor
//
// Use: internal
SoV1NodekitCatalogEntry::SoV1NodekitCatalogEntry( const SbName &theName,
const SoType &theType , const SoType &theDefaultType,
const SbName &theParentName,
const SbName &theRightSiblingName, SbBool theListPart,
const SbPList &theListItemTypes,
SbBool thePublicPart )
//
////////////////////////////////////////////////////////////////////////
{
name = theName;
type = theType;
defaultType = theDefaultType;
leafPart = TRUE; // everything is a leaf 'til given a child
parentName = theParentName;
rightSiblingName = theRightSiblingName;
listPart = theListPart;
listItemTypes.copy( theListItemTypes );
publicPart = thePublicPart;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Print contents for debugging purposes
//
// Use: internal
void
SoV1NodekitCatalogEntry::printCheck() const
//
////////////////////////////////////////////////////////////////////////
{
fprintf( stdout," name = %s, type = %s, defaultType = %s\n",
name.getString(), type.getName().getString(), defaultType.getName().getString() );
fprintf( stdout," parentName = %s\n", parentName.getString() );
fprintf( stdout," sibling = %s, listPart = %d\n",
rightSiblingName.getString(), listPart );
if ( listPart ) {
fprintf( stdout, "listItemTypes = " );
for ( int i = 0; i < listItemTypes.getLength(); i++ ) {
fprintf( stdout," %d ",
((SoType *) listItemTypes[i])->getName().getString() );
}
fprintf( stdout, "\n" );
}
fprintf( stdout," publicPart = %d\n", publicPart );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Creates a new copy of this catalog
//
// Use: private
SoV1NodekitCatalogEntry *
SoV1NodekitCatalogEntry::clone() const
//
////////////////////////////////////////////////////////////////////////
{
// make a clone with the current type and defaultType...
return clone( type, defaultType );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Creates a new copy of this catalog, but sets the type to newType
//
// Use: private
SoV1NodekitCatalogEntry *
SoV1NodekitCatalogEntry::clone( const SoType &newType,
const SoType &newDefaultType ) const
//
////////////////////////////////////////////////////////////////////////
{
SoV1NodekitCatalogEntry *theClone;
theClone = new SoV1NodekitCatalogEntry( name, newType, newDefaultType,
parentName, rightSiblingName, listPart, listItemTypes, publicPart );
theClone->leafPart = leafPart;
return theClone;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Creates a new copy of this catalog
//
// Use: public
void
SoV1NodekitCatalogEntry::addListItemType( const SoType &typeToAdd )
//
////////////////////////////////////////////////////////////////////////
{
SoType *typePtr = new SoType();
*typePtr = typeToAdd;
listItemTypes.append( typePtr );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Looks for the given part.
// Checks this part, then recursively checks all entries in the
// catalog of this part (it gets its own catalog by looking
// at the catalog for the 'dummy' for this type, which is accessed
// through: type.createInstance()->getNodekitCatalog()
// or, if type is an abstract type,
// uses defaultType.createInstance()->getNodekitCatalog()
//
// Use: public
SbBool
SoV1NodekitCatalogEntry::recursiveSearch( const SbName &nameToFind,
SbPList *typesChecked ) const
//
////////////////////////////////////////////////////////////////////////
{
const SoV1NodekitCatalog *subCat;
// is this the part of my dreams?
if ( name == nameToFind )
return TRUE;
// make sure the part isn't a list
if ( listPart == TRUE )
return FALSE;
// make sure the part is subclassed off of SoV1BaseKit
if ( !type.isDerivedFrom( SoV1BaseKit::getClassTypeId() ))
return FALSE;
// avoid an infinite search loop by seeing if this type has already been
// checked...
if ( typesChecked->find( (void *) type.getName().getString()) != -1 )
return FALSE;
// if it's still ok, then search within the catalog of this part
// first check each name:
const SoV1BaseKit *inst = (const SoV1BaseKit *) type.createInstance();
if ( inst == NULL )
inst = (const SoV1BaseKit *) defaultType.createInstance();
#ifdef DEBUG
if ( inst == NULL ) {
SoDebugError::post("SoV1NodekitCatalogEntry::recursiveSearch",
"part type and defaultType are both abstract classes");
abort();
}
#endif
subCat = inst->getNodekitCatalog();
int i;
for( i = 0; i < subCat->getNumEntries(); i++ ) {
if ( subCat->getName( i ) == nameToFind )
return TRUE;
}
// at these point, we've checked all the names in this class, so
// we can add it to typesChecked
typesChecked->append( (void *) type.getName().getString() );
// then, recursively check each part
for( i = 0; i < subCat->getNumEntries(); i++ ) {
if ( subCat->recursiveSearch( i, nameToFind, typesChecked ) )
return TRUE;
}
return FALSE; // couldn't find it ANYwhere!
}
////////////////////////////////////////////////////////////////////////
//
// Class:
// SoV1NodekitCatalog
//
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
// Description:
// Constructor
//
// Use: internal
SoV1NodekitCatalog::SoV1NodekitCatalog()
//
////////////////////////////////////////////////////////////////////////
{
numEntries = 0;
entries = NULL;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Destructor
//
// Use: internal
SoV1NodekitCatalog::~SoV1NodekitCatalog()
//
////////////////////////////////////////////////////////////////////////
{
// delete all the members of the entries array
for ( int i = 0; i < numEntries; i++ )
delete entries[i];
// delete the entries array itself
if (entries != NULL)
delete entries;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Prints out contents of the catalog for debuggin purposes
//
// Use: internal
void
SoV1NodekitCatalog::printCheck() const
//
////////////////////////////////////////////////////////////////////////
{
fprintf(stdout,"catalog printout: number of entries = %d\n", numEntries );
for( int i = 0; i < numEntries; i++ ) {
fprintf(stdout,"#%d\n", i );
entries[i]->printCheck();
}
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the partNumber of an entry given its reference name.
//
// Use: internal
int
SoV1NodekitCatalog::getPartNumber( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
void *castPNum;
if ( partNameDict.find( (unsigned long) theName.getString(), castPNum ) )
#if (_MIPS_SZPTR == 64 || __ia64)
return ( (int) ((long) castPNum) ); // System long
#else
return ( (int) castPNum );
#endif
else
return SO_V1_CATALOG_NAME_NOT_FOUND;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the name of an entry given its partNumber.
//
// Use: internal
const SbName &
SoV1NodekitCatalog::getName( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
// return the name of the entry, if you can find it.
if ( thePartNumber >= 0 && thePartNumber < numEntries )
return entries[thePartNumber]->getName();
else
return *emptyName;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the type of an entry.
//
// Use: internal
const SoType &
SoV1NodekitCatalog::getType( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
// return the type of the entry, if you can find it.
if ( thePartNumber >= 0 && thePartNumber < numEntries )
return entries[thePartNumber]->getType();
else
return *badType;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the type of an entry.
//
// Use: internal
const SoType &
SoV1NodekitCatalog::getType( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
return( getType( getPartNumber( theName ) ));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the default type of an entry.
//
// Use: internal
const SoType &
SoV1NodekitCatalog::getDefaultType( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
// return the defaultType of the entry, if you can find it.
if ( thePartNumber >= 0 && thePartNumber < numEntries )
return entries[thePartNumber]->getDefaultType();
else
return *badType;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the defaultType of an entry.
//
// Use: internal
const SoType &
SoV1NodekitCatalog::getDefaultType( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
return( getDefaultType( getPartNumber( theName ) ));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding 'leafPart' of an entry.
//
// Use: internal
SbBool
SoV1NodekitCatalog::isLeaf( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
// return the type of the entry, if you can find it.
if ( thePartNumber >= 0 && thePartNumber < numEntries )
return entries[thePartNumber]->isLeaf();
else
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding 'leafPart' of an entry.
//
// Use: internal
SbBool
SoV1NodekitCatalog::isLeaf( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
return( isLeaf( getPartNumber( theName ) ));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the name of the parent of an entry.
//
// Use: internal
const SbName &
SoV1NodekitCatalog::getParentName( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
// return the entry, if you can find it.
if ( thePartNumber >= 0 && thePartNumber < numEntries )
return entries[thePartNumber]->getParentName();
else
return *emptyName;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the name of the parent of an entry.
//
// Use: internal
const SbName &
SoV1NodekitCatalog::getParentName( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
return( getParentName( getPartNumber( theName ) ));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the name of the parent of an entry.
//
// Use: internal
int
SoV1NodekitCatalog::getParentPartNumber( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
const SbName pName = getParentName( thePartNumber );
return( getPartNumber( pName ) );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the name of the parent of an entry.
//
// Use: internal
int
SoV1NodekitCatalog::getParentPartNumber( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
const SbName pName = getParentName( theName );
return( getPartNumber( pName ) );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the name of the right sibling of an entry.
//
// Use: internal
const SbName &
SoV1NodekitCatalog::getRightSiblingName( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
// return the entry, if you can find it.
if ( thePartNumber >= 0 && thePartNumber < numEntries )
return entries[thePartNumber]->getRightSiblingName();
else
return *emptyName;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the name of the RightSiblingName of an entry.
//
// Use: internal
const SbName &
SoV1NodekitCatalog::getRightSiblingName( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
return( getRightSiblingName( getPartNumber( theName ) ));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the name of the rightSibling of an entry.
//
// Use: internal
int
SoV1NodekitCatalog::getRightSiblingPartNumber( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
const SbName sName = getRightSiblingName( thePartNumber );
return( getPartNumber( sName ) );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the name of the rightSibling of an entry.
//
// Use: internal
int
SoV1NodekitCatalog::getRightSiblingPartNumber( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
const SbName sName = getRightSiblingName( theName );
return( getPartNumber( sName ) );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding 'listPart' of an entry.
//
// Use: internal
SbBool
SoV1NodekitCatalog::isList( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
// return the type of the entry, if you can find it.
if ( thePartNumber >= 0 && thePartNumber < numEntries )
return entries[thePartNumber]->isList();
else
return FALSE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding 'listPart' of an entry.
//
// Use: internal
SbBool
SoV1NodekitCatalog::isList( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
return( isList( getPartNumber( theName ) ));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the list item type of an entry.
//
// Use: internal
const SbPList &
SoV1NodekitCatalog::getListItemTypes( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
// return the type of the entry, if you can find it.
if ( thePartNumber >= 0 && thePartNumber < numEntries )
return entries[thePartNumber]->getListItemTypes();
else
return ( *emptyList );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding the list item type of an entry.
//
// Use: internal
const SbPList &
SoV1NodekitCatalog::getListItemTypes( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
return( getListItemTypes( getPartNumber( theName ) ));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding 'publicPart' of an entry.
//
// Use: internal
SbBool
SoV1NodekitCatalog::isPublic( int thePartNumber ) const
//
////////////////////////////////////////////////////////////////////////
{
// return whether the part is public, if you can find it.
if ( thePartNumber >= 0 && thePartNumber < numEntries )
return entries[thePartNumber]->isPublic();
else
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For finding 'publicPart' of an entry.
//
// Use: internal
SbBool
SoV1NodekitCatalog::isPublic( const SbName &theName ) const
//
////////////////////////////////////////////////////////////////////////
{
return( isPublic( getPartNumber( theName ) ));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For adding an allowable child-type to an entry.
// This will only make a difference if the entry has listPart set to TRUE
//
// Use: public
void
SoV1NodekitCatalog::addListItemType( int thePartNumber,
const SoType &typeToAdd )
//
////////////////////////////////////////////////////////////////////////
{
// add typeToAdd to the entry's listItemTypes, if you can find
// the entry...
if ( thePartNumber >= 0 && thePartNumber < numEntries )
entries[thePartNumber]->addListItemType( typeToAdd );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For adding an allowable child-type to an entry.
// This will only make a difference if the entry has listPart set to TRUE
//
// Use: public
void
SoV1NodekitCatalog::addListItemType( const SbName &theName,
const SoType &typeToAdd )
//
////////////////////////////////////////////////////////////////////////
{
addListItemType( getPartNumber( theName ), typeToAdd );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
//
// For changing the type and defaultType of an entry.
// The new types must be subclasses of the types already existing in the
// entry.
// For example, in SoV1ShapeKit, the part "shape" has type SoShape and
// default type SoSphere. Any shape node is acceptable, but be default a
// sphere will be built.
// Well, when creating the SoV1VertexShapeKit class, a call of:
// narrowTypes( "shape", SoVertexShape::getClassTypeId(),
// SoFaceSet::getClassTypeId())
// might be used. This would reflect the fact that:
// Only vertext shapes may be put in the "shape" part, not just any shape.
// And also, by default, a faceSet will be built, not a sphere.
//
// Use: public
void
SoV1NodekitCatalog::narrowTypes( const SbName &theName,
const SoType &newType, const SoType &newDefaultType )
//
////////////////////////////////////////////////////////////////////////
{
int thePartNumber = getPartNumber( theName );
if ( thePartNumber < 0 || thePartNumber >= numEntries )
return;
SoV1NodekitCatalogEntry *theEntry = entries[thePartNumber];
// Checks that [1] newDefaultType is not an abstract type, and
// [2] newDefaultType is a subclass of newType
if ( !checkNewTypes( newType, newDefaultType ) )
return;
const SoType oldType = theEntry->getType();
const SoType oldDefaultType = theEntry->getDefaultType();
// Make sure that the new types is derived from the old type.
// Parts in derived classes must be subclasses of the types they
// belong to when cast to the parent classes.
if ( !newType.isDerivedFrom( oldType ) ) {
#ifdef DEBUG
const char *newName = newType.getName().getString();
const char *oldName = oldType.getName().getString();
SoDebugError::post("SoV1NodekitCatalogEntry::narrowTypes",
"The newType %s is not a subclass of the oldType "
"%s. Cannot narrow the type from %s to %s",
newName, oldName, oldName, newName);
#endif
return;
}
// passed all the tests!
theEntry->setTypes( newType, newDefaultType );
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Creates a new copy of this catalog
//
// Use: public
SoV1NodekitCatalog *
SoV1NodekitCatalog::clone( const SoType &typeOfThis ) const
//
////////////////////////////////////////////////////////////////////////
{
SoV1NodekitCatalog *theClone;
theClone = new SoV1NodekitCatalog;
theClone->numEntries = numEntries;
if (numEntries == 0)
theClone->entries = NULL;
else {
theClone->entries = new ( SoV1NodekitCatalogEntry *[numEntries]);
for (int i = 0; i < numEntries; i++) {
if ( entries[i]->getName() == "this" )
theClone->entries[i] = entries[i]->clone( typeOfThis,
typeOfThis );
else
theClone->entries[i] = entries[i]->clone();
theClone->partNameDict.enter( (unsigned long)
entries[i]->getName().getString(),
(void *) (unsigned long) i );
}
}
return theClone;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Used as a check when adding a new entry to a catalog.
// Checks that the name is not NULL and not empty.
//
// Use: private
SbBool
SoV1NodekitCatalog::checkName( const SbName &theName ) // proposed name
//
////////////////////////////////////////////////////////////////////////
{
// CHECK IF IT'S NULL
if ( theName.getString() == NULL ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkName",
"given name is NULL" );
#endif
return FALSE;
}
// CHECK IF IT'S EMPTY
if ( theName == "" ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkName",
"given name is the empty string" );
#endif
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Used as a check when adding a new entry to a catalog.
// Checks that the name is OK to use for the new entry.
//
// Use: private
SbBool
SoV1NodekitCatalog::checkNewName( const SbName &theName ) // proposed name
//
////////////////////////////////////////////////////////////////////////
{
if ( !checkName( theName ) )
return FALSE;
// CHECK IF IT'S UNIQUE FOR THIS CATALOG
if ( getPartNumber( theName ) == SO_V1_CATALOG_NAME_NOT_FOUND ) {
return TRUE;
}
else {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkNewName",
"the name %s is already in this catalog",
theName.getString() );
#endif
return FALSE;
}
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Used as a check when adding a new entry to a catalog.
// Checks that the type is not for an abstract node type.
//
// Use: private
SbBool
SoV1NodekitCatalog::checkNewTypes( const SoType &theType, // proposed type
const SoType &theDefaultType ) // and default
//
////////////////////////////////////////////////////////////////////////
{
if ( !theDefaultType.canCreateInstance()) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkNewTypes",
" the defaultType %s is an abstract class, and cannot be part of a nodekits structure", theDefaultType.getName().getString() );
#endif
return FALSE;
}
if ( !theDefaultType.isDerivedFrom( theType ) ) {
#ifdef DEBUG
const char *defName = theDefaultType.getName().getString();
SoDebugError::post("SoV1NodekitCatalogEntry::checkNewTypes",
"the defaultType %s is not a subclass of the type "
"%s. It can not be part of a nodekits structure",
defName, theType.getName().getString() );
#endif
return FALSE;
}
else
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Used as a check when adding a new entry to a catalog.
// Checks that the name is OK to use the parent for a new entry.
//
// Use: private
SbBool
SoV1NodekitCatalog::checkAndGetParent(
const SbName &theName, // the child's name
const SbName &theParentName, // proposed parent name
SoV1NodekitCatalogEntry *& parentEntry ) // corresponding entry filled
// in this method
//
////////////////////////////////////////////////////////////////////////
{
// CHECK FOR "THIS"
// The string "this" means that a node is to be the nodekit node itself
// In this case, return NULL as the parentEntry, and a status of TRUE!
if ( theName == "this" ) {
// 'this' has no parent
parentEntry = NULL;
return TRUE;
}
else {
// only 'this' can have no parent
if ( !checkName( theParentName ) )
return FALSE;
}
// CHECK THAT THE PARENT IS IN THE CATALOG
int parentPartNumber = getPartNumber( theParentName );
if ( parentPartNumber == SO_V1_CATALOG_NAME_NOT_FOUND ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkAndGetParent",
"requested parent >> %s << is not in this catalog",
theParentName.getString() );
#endif
return FALSE;
}
parentEntry = entries[ parentPartNumber ];
// CHECK THE NODE TYPE OF THE PARENT
// [1] it must be a subclass of SoGroup, or you can't add children to it.
if ( !parentEntry->getType().isDerivedFrom( SoGroup::getClassTypeId() ) ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkAndGetParent",
"requested parent >> %s << is a node that is not subclassed from SoGroup, so it can't have children",
theParentName.getString() );
#endif
return FALSE;
}
// [2] Unless it is 'this', the parent can NOT be subclass of SoV1BaseKit.
// This is because you can only add child nodes to an nodekit through
// its own class's nodekitCatalog
if ( theParentName != "this" &&
parentEntry->getType().isDerivedFrom( SoV1BaseKit::getClassTypeId()) ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkAndGetParent",
" requested parent >> %s << is a node that is subclassed from SoV1BaseKit, so it can't children except through its own class's nodekitCatalog",
theParentName.getString());
#endif
return FALSE;
}
// MAKE SURE THAT THE NODE HAS NOT BEEN DESIGNATED AS A LIST
if ( parentEntry->isList() == TRUE ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkAndGetParent",
"Requested parent >> %s << is a node that has been designated as a list. It can not have explicit children in the catalog, although nodes can be added to the list for a given instance by using the special list editting methods on the nodekit node.", theParentName.getString() );
#endif
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Used as a check when adding a new entry to a catalog.
// Finds the left and right siblings for the new entry.
// Also, checks that the right sibling exists in the catalog (unless
// the name is "", in which case the new entry is to be the rightmost child
//
// Use: private
SbBool
SoV1NodekitCatalog::checkAndGetSiblings(
const SbName &theParentName, // parent name
const SbName &theRightSiblingName, // proposed sibling name
SoV1NodekitCatalogEntry *& leftEntry, // new left (to be filled in)
SoV1NodekitCatalogEntry *& rightEntry ) // new right (to be filled )
//
////////////////////////////////////////////////////////////////////////
{
leftEntry = NULL;
rightEntry = NULL;
for ( int i = 0; i < numEntries; i++ ) {
// is it left?
if ( entries[i]->getParentName() == theParentName &&
entries[i]->getRightSiblingName() == theRightSiblingName )
leftEntry = entries[i];
// is it right?
else if ( entries[i]->getParentName() == theParentName &&
theRightSiblingName == entries[i]->getName() )
rightEntry = entries[i];
}
if ( ( rightEntry == NULL ) && ( theRightSiblingName != "" ) ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkAndGetSiblings",
" Requested right sibling >> %s << can not be found in the nodekitCatalog", theRightSiblingName.getString() );
#endif
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Used as a check when adding a new entry to a catalog.
// Called if the new node is to be a list of other nodes.
// Checks that the given type is OK as a list.
//
// Use: private
SbBool
SoV1NodekitCatalog::checkCanTypesBeList( const SoType &theType,
const SoType &theDefaultType )
//
////////////////////////////////////////////////////////////////////////
{
// CHECK IF IT'S A GROUP OR SEPARATOR
if ( !(theType == SoGroup::getClassTypeId() ||
theType == SoSeparator::getClassTypeId() ||
theType == SoSwitch::getClassTypeId() )) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkCanTypesBeList",
" requested node type can not be a list since it is neither an SoGroup, an SoSeparator, or an SoSwitch");
#endif
return FALSE;
}
if ( !(theDefaultType == SoGroup::getClassTypeId() ||
theDefaultType == SoSeparator::getClassTypeId() ||
theDefaultType == SoSwitch::getClassTypeId() )) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::checkCanTypesBeList",
" requested node type can not be a list since it is neither an SoGroup, an SoSeparator, or an SoSwitch");
#endif
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// For adding a new entry into the nodekitCatalog
//
// Use: internal
SbBool
SoV1NodekitCatalog::addEntry( const SbName &theName,
const SoType &theType,
const SoType &theDefaultType,
const SbName &theParentName,
const SbName &theRightSiblingName,
SbBool theListPart,
const SoType &theListItemType,
SbBool thePublicPart )
//
////////////////////////////////////////////////////////////////////////
{
SoV1NodekitCatalogEntry *parentEntry, *rightEntry, *leftEntry;
SoV1NodekitCatalogEntry *newEntry;
SoV1NodekitCatalogEntry **newArray;
// CHECK IF THE NEW ENTRY IS OK
if ( !checkNewName( theName ) )
return FALSE;
if ( !checkNewTypes( theType, theDefaultType ) ) {
#ifdef DEBUG
SoDebugError::post("SoV1NodekitCatalogEntry::addEntry",
"error creating catalog entry %s", theName.getString());
#endif
return FALSE;
}
if ( !checkAndGetParent( theName, theParentName, parentEntry ) )
return FALSE;
if ( !checkAndGetSiblings( theParentName, theRightSiblingName,
leftEntry, rightEntry ) )
return FALSE;
if ( theListPart && !checkCanTypesBeList( theType, theDefaultType ) )
return FALSE;
// IF ALL TESTS WERE PASSED...
// expand the list by one slot
newArray = new ( SoV1NodekitCatalogEntry *[numEntries + 1]);
if ( entries != NULL ) {
for (int i = 0; i < numEntries; i++ )
newArray[i] = entries[i];
delete entries;
}
entries = newArray;
numEntries++;
// make a list containing only the given list item type.
SbPList *listItemTypeList = new SbPList( 0 );
SoType *typePtr = new SoType;
*typePtr = theListItemType;
listItemTypeList->append( (void *) typePtr );
// create the new entry
newEntry = new SoV1NodekitCatalogEntry( theName, theType, theDefaultType,
theParentName, theRightSiblingName,theListPart,*listItemTypeList,
thePublicPart);
// enter the new entry in the array
entries[numEntries - 1] = newEntry;
// add the new name to the quick-reference part name dictionary
partNameDict.enter( (unsigned long) theName.getString(),
(void *) (unsigned long) (numEntries - 1));
// parent is no longer a leaf node in the nodekit structure
if ( parentEntry != NULL )
parentEntry->setLeaf( FALSE );
// stitch up sibling names.
if ( leftEntry != NULL )
leftEntry->setRightSiblingName( theName );
return TRUE;
}
////////////////////////////////////////////////////////////////////////
//
// Description:
// Looks for part with the given name within the template.
// Recursively Checks 'partNumber' only.
//
// See SoV1NodekitCatalogEntry::recursiveSearch for more info...
//
// Use: public
SbBool
SoV1NodekitCatalog::recursiveSearch( int partNumber,
const SbName &nameToFind,
SbPList *typesChecked ) const
//
////////////////////////////////////////////////////////////////////////
{
// just call the recursive search method on the given entry...
return( entries[partNumber]->recursiveSearch( nameToFind, typesChecked ));
}