Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
NameAttribute.c
/* |
* Quickdraw 3D sample code |
* |
* This file shows how to implement a simple custom attribute as a plug-in. |
* |
* Nick Thompson, nickt@apple.com, November 1996 |
* |
* Please send technical questions that you may have about this code |
* to devsupport@apple.com |
* |
* Based on attributelib. For more information about the basic principles |
* of this, check the article in develop, plugins in the form of shared |
* libraries were just a twinkle in kent's eye then. The main difference |
* is in the way these puppies get registered, and in the name sapce. |
* |
* This sample code has minimal error checking. More should be added if this |
* code is used in a production quality product. |
* |
* Revision History: |
* 8/12/97 RDD Changed register and unregister functions and fixed |
* CopyReplace method. |
*/ |
#include "QD3D.h" |
#include "QD3DExtension.h" |
#include "QD3DGeometry.h" |
#include "QD3DIO.h" |
#include "QD3DSet.h" |
#include "QD3DString.h" |
#include "QD3DView.h" |
#include <Errors.h> |
#include <string.h> |
#include "NameAttribute.h" |
/****************************************************************************** |
** |
** Globals |
** |
*****************************************************************************/ |
static TQ3XObjectClass pNameAttributeClass = NULL; |
static unsigned long pSharedLibrary = 0; |
static const short pMajorVersion = 1 ; |
static const short pMinorVersion = 5 ; |
/****************************************************************************** |
** |
** Function prototypes for functions local to this file |
** |
*****************************************************************************/ |
static TQ3Status NameAttribute_Traverse( |
TQ3Object unused, |
TQ3StringObject *stringObject, |
TQ3ViewObject view) ; |
static TQ3Status NameAttribute_ReadData( |
TQ3SetObject attributeSet, |
TQ3FileObject file) ; |
static TQ3Status NameAttribute_CopyAdd( |
TQ3StringObject *src, |
TQ3StringObject *dst) ; |
static TQ3Status NameAttribute_CopyReplace( |
TQ3StringObject *src, |
TQ3StringObject *dst) ; |
static TQ3Status NameAttribute_Delete( |
TQ3StringObject *stringObject) ; |
static TQ3XFunctionPointer NameAttribute_MetaHandler( |
TQ3XMethodType methodType) ; |
/*===========================================================================*\ |
* |
* Routine: NameAttribute_SetName() |
* |
* Comments: Utility function to add a name on an shape object, geometry |
* object, or attribute set. |
* |
\*===========================================================================*/ |
TQ3Status NameAttribute_SetName( |
TQ3Object object, |
char *name) |
{ |
TQ3StringObject string = NULL; |
TQ3AttributeSet set = NULL; |
TQ3Status status = kQ3Success; |
TQ3ElementType myElementType ; |
/* |
* NOTE: You cannot just use the type as it was registered, |
* so you have two options: the first is to save a reference |
* to the element type that we got back from the register function |
* the second is to use the global class to get the type. Since |
* we already need to keep the class global, that's what I decided |
* to do here. (This code is not optimal) |
*/ |
Q3XObjectClass_GetType( pNameAttributeClass, &myElementType) ; |
if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) { |
string = Q3CString_New(name); |
if( string == NULL) { |
status = kQ3Failure; |
goto cleanExit; |
} |
if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) { |
Q3Geometry_GetAttributeSet(object, &set); |
if( set == NULL ) { |
set = Q3AttributeSet_New(); |
if( set == NULL ) { |
status = kQ3Failure; |
goto cleanExit; |
} |
Q3Geometry_SetAttributeSet(object, set); |
} |
} else { |
Q3Shape_GetSet(object, &set); |
if( set == NULL ) { |
set = Q3Set_New(); |
if( set == NULL ) { |
status = kQ3Failure; |
goto cleanExit; |
} |
Q3Shape_SetSet(object, set); |
} |
} |
if( Q3Set_Add(set, myElementType, &string) == kQ3Failure ) { |
status = kQ3Failure; |
goto cleanExit; |
} |
} else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) { |
string = Q3CString_New(name); |
if( string == NULL) { |
status = kQ3Failure; |
goto cleanExit; |
} |
if( Q3AttributeSet_Add(object, myElementType, &string) == kQ3Failure ) { |
status = kQ3Failure; |
goto cleanExit; |
} |
} else |
status = kQ3Failure; |
cleanExit: |
if( string ) |
Q3Object_Dispose(string); |
if( set ) |
Q3Object_Dispose(set); |
return status; |
} |
/*===========================================================================*\ |
* |
* Routine: NameAttribute_GetName() |
* |
* Comments: Utility function to get a name from a shape object, geometry |
* object, or an attribute set. |
* |
\*===========================================================================*/ |
TQ3Status NameAttribute_GetName( |
TQ3Object object, |
char *name) |
{ |
TQ3StringObject string = NULL; |
TQ3AttributeSet set = NULL; |
TQ3Status status = kQ3Success; |
char *nameString = NULL ; |
TQ3ElementType myElementType ; |
/* |
* NOTE: You cannot just use the type as it was registered, |
* so you have two options: the first is to save a reference |
* to the element type that we got back from the register function |
* the second is to use the global class to get the type. Since |
* we already need to keep the class global, that's what I decided |
* to do here. Set up the element type: |
*/ |
Q3XObjectClass_GetType( pNameAttributeClass, &myElementType) ; |
if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) { |
if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) { |
Q3Geometry_GetAttributeSet(object, &set); |
if( set == NULL ) { |
status = kQ3Failure; |
goto cleanExit; |
} |
} |
else |
{ |
Q3Shape_GetSet(object, &set); |
} |
if( Q3Set_Contains ( set, myElementType ) == kQ3True ) { |
status = Q3Set_Get ( set, myElementType, &string ) ; |
if( string == NULL || status == kQ3Failure ) { |
status = kQ3Failure; |
goto cleanExit; |
} |
} |
} |
else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) { |
if( Q3AttributeSet_Get(object, myElementType, &string) == kQ3Failure ) { |
status = kQ3Failure; |
goto cleanExit; |
} |
} else |
status = kQ3Failure; |
if( status != kQ3Failure && string != NULL ) |
{ |
/* get the string from the CString object */ |
status = Q3CString_GetString ( string, &nameString ) ; |
strcpy( name, nameString ) ; |
status = Q3CString_EmptyData(&nameString); |
} |
else |
{ |
*name = NULL ; |
} |
cleanExit: |
if( string ) |
Q3Object_Dispose(string); |
if( set ) |
Q3Object_Dispose(set); |
return status; |
} |
/*===========================================================================*\ |
* |
* Routine: NameAttributeClassRegister() |
* |
* Comments: Registers the Name attribute class. |
* |
\*===========================================================================*/ |
TQ3Status NameAttribute_Register( void ) |
{ |
TQ3ElementType myElementType = kQ3ObjectTypeInvalid ; /* discarded */ |
/* |
* Register the new name element class. NOTE: this will change myElementType |
* to be a unique type. This helps to prevent namespace clashes, but you MUST |
* remember to use what you are passed back when accessing the elements of a set. |
* |
* You can either store the value returned in myElementType or use the global |
* pNameAttributeClass. In this sample we use the latter approach. Now that we |
* have a reference to the class around we can use that to get the type for |
* the calls that need the type using the following API call: |
* |
* Q3XObjectClass_GetType( pNameAttributeClass, &myElementType) ; |
*/ |
pNameAttributeClass = |
Q3XElementClass_Register( |
&myElementType, |
kElementTypeNameString, |
sizeof(TQ3StringObject), |
NameAttribute_MetaHandler ); |
if (pNameAttributeClass == NULL) |
return kQ3Failure; |
return kQ3Success; |
} |
/* Name attribute CFM init and termination routines */ |
OSErr NameAttribute_ConnectionInitializationRoutine(InitBlockPtr initBlock) |
{ |
TQ3Status theStatus; |
TQ3XSharedLibraryInfo sharedLibraryInfo; |
OSErr osErr; |
/* |
* Register this custom attribute/element with QuickDraw 3D using the |
* callback Q3XSharedLibrary_Register which is passed the register function |
* and the closureID (_not_ the connectionID). |
*/ |
sharedLibraryInfo.registerFunction = NameAttribute_Register; |
sharedLibraryInfo.sharedLibrary = (unsigned long)initBlock->connectionID; |
theStatus = Q3XSharedLibrary_Register(&sharedLibraryInfo); |
if (theStatus == kQ3Success) { |
pSharedLibrary = (unsigned long)initBlock->connectionID; |
osErr = noErr; |
} |
else { |
osErr = fragMgrInitErr; /* ...or some other meaningfull error */ |
} |
return osErr; |
} |
void NameAttribute_ConnectionTerminationRoutine (void) |
{ |
TQ3Status theStatus ; |
if( pSharedLibrary != NULL ) { |
theStatus = Q3XSharedLibrary_Unregister(pSharedLibrary); |
pSharedLibrary = NULL; |
} |
theStatus = NameAttribute_Unregister() ; |
} |
/* |
* Static Functions |
*/ |
static TQ3Status NameAttribute_Traverse( |
TQ3Object unused, |
TQ3StringObject *stringObject, |
TQ3ViewObject view) |
{ |
(void) unused; |
if (stringObject == NULL || *stringObject == NULL) |
return kQ3Success; |
if (Q3XView_SubmitWriteData(view, 0, NULL, NULL) == kQ3Failure) { |
return kQ3Failure; |
} |
if (Q3Object_Submit( *stringObject, view) == kQ3Failure) { |
return kQ3Failure; |
} |
return kQ3Success; |
} |
static TQ3Status NameAttribute_ReadData( |
TQ3SetObject attributeSet, |
TQ3FileObject file) |
{ |
TQ3StringObject stringObject; |
TQ3Status status; |
TQ3ElementType myElementType ; |
/* |
* NOTE: You cannot just use the type as it was registered, |
* so you have two options: the first is to save a reference |
* to the element type that we got back from the register function |
* the second is to use the global class to get the type. Since |
* we already need to keep the class global, that's what I decided |
* to do here. |
*/ |
Q3XObjectClass_GetType( pNameAttributeClass, &myElementType) ; |
stringObject = Q3File_ReadObject(file); |
status = Q3Set_Add(attributeSet, myElementType, &stringObject); |
Q3Object_Dispose(stringObject); |
/* |
* Note that the string object has a reference count of 1, |
* which will be taken care of in the dispose |
*/ |
return status; |
} |
static TQ3Status NameAttribute_CopyAdd( |
TQ3StringObject *src, |
TQ3StringObject *dst) |
{ |
*dst = Q3Shared_GetReference(*src); |
return (*dst != NULL) ? kQ3Success : kQ3Failure; |
} |
static TQ3Status NameAttribute_CopyReplace( |
TQ3StringObject *src, |
TQ3StringObject *dst) |
{ |
TQ3StringObject tempString; |
/* |
* It is always good form to get a reference first, |
* in case src and dst point to the same object |
*/ |
tempString = Q3Shared_GetReference(*src); |
if (tempString == NULL) |
return kQ3Failure; |
if( *dst ) |
Q3Object_Dispose( *dst ); |
*dst = tempString; |
return kQ3Success; |
} |
static TQ3Status NameAttribute_Delete( |
TQ3StringObject *stringObject) |
{ |
if (*stringObject != NULL) { |
Q3Object_Dispose(*stringObject); |
*stringObject = NULL; |
} |
return kQ3Success; |
} |
TQ3Status NameAttribute_Unregister( |
void) |
{ |
TQ3Status returnVal = kQ3Failure ; |
if ( pNameAttributeClass != NULL ) |
{ |
/* |
* QuickDraw 3D unregisters this object together with all |
* other registered objects in the system on Q3Exit. |
*/ |
pNameAttributeClass = NULL ; |
returnVal = kQ3Success ; |
} |
return returnVal ; |
} |
/* |
* NameAttribute_MetaHandler |
*/ |
static TQ3XFunctionPointer NameAttribute_MetaHandler( |
TQ3XMethodType methodType) |
{ |
switch (methodType) |
{ |
case kQ3XMethodTypeObjectClassVersion: |
return (TQ3XFunctionPointer) |
Q3_OBJECT_CLASS_VERSION(pMajorVersion, pMinorVersion); |
case kQ3XMethodTypeObjectTraverse: |
return (TQ3XFunctionPointer) NameAttribute_Traverse; |
case kQ3XMethodTypeObjectReadData: |
return (TQ3XFunctionPointer) NameAttribute_ReadData; |
case kQ3XMethodTypeElementCopyAdd: |
case kQ3XMethodTypeElementCopyGet: |
case kQ3XMethodTypeElementCopyDuplicate: |
return (TQ3XFunctionPointer) NameAttribute_CopyAdd; |
case kQ3XMethodTypeElementCopyReplace: |
return (TQ3XFunctionPointer) NameAttribute_CopyReplace; |
case kQ3XMethodTypeElementDelete: |
return (TQ3XFunctionPointer) NameAttribute_Delete; |
default: |
return (TQ3XFunctionPointer) NULL; |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14