* Source/GSNibLoading.m: Reorganization and simplification of

nib loading logic in NSIBObjectData.  Also documentation for 
	NSIBObjectData and NSClassSwapper.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@27575 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
gcasa 2009-01-12 01:44:39 +00:00
parent 240c45bd83
commit 1c6f7ceaa0
2 changed files with 234 additions and 55 deletions

View file

@ -1,3 +1,9 @@
2009-01-11 20:49-EST Gregory John Casamento <greg_casamento@yahoo.com>
* Source/GSNibLoading.m: Reorganization and simplification of
nib loading logic in NSIBObjectData. Also documentation for
NSIBObjectData and NSClassSwapper.
2009-01-10 15:49-EST Gregory John Casamento <greg_casamento@yahoo.com> 2009-01-10 15:49-EST Gregory John Casamento <greg_casamento@yahoo.com>
* Source/NSToolbarItem.m: Added _sendAction: method to send * Source/NSToolbarItem.m: Added _sendAction: method to send

View file

@ -336,7 +336,7 @@ static BOOL _isInInterfaceBuilder = NO;
} }
if ([coder containsValueForKey: @"NSFrameAutosaveName"]) if ([coder containsValueForKey: @"NSFrameAutosaveName"])
{ {
ASSIGN(_autosaveName, [coder decodeObjectForKey: @"NSFrameAutosaveName"]); ASSIGN(_autosaveName, [coder decodeObjectForKey: @"NSFrameAutosaveName"]);
} }
if ([coder containsValueForKey: @"NSWindowTitle"]) if ([coder containsValueForKey: @"NSWindowTitle"])
{ {
@ -1025,6 +1025,9 @@ static BOOL _isInInterfaceBuilder = NO;
} }
@end @end
/**
* This class represents an image or a sound which is referenced by the nib file.
*/
@implementation NSCustomResource @implementation NSCustomResource
- (void) setClassName: (NSString *)className - (void) setClassName: (NSString *)className
{ {
@ -1090,7 +1093,15 @@ static BOOL _isInInterfaceBuilder = NO;
} }
@end @end
/**
* Category to add methods to NSKeyedUnarchiver which are needed during
* nib reading.
*/
@implementation NSKeyedUnarchiver (NSClassSwapperPrivate) @implementation NSKeyedUnarchiver (NSClassSwapperPrivate)
/**
* This method is used to replace oldObj with newObj
* in the map that is maintained in NSKeyedUnarchiver.
*/
- (BOOL) replaceObject: (id)oldObj withObject: (id)newObj - (BOOL) replaceObject: (id)oldObj withObject: (id)newObj
{ {
unsigned int i = 0; unsigned int i = 0;
@ -1111,11 +1122,18 @@ static BOOL _isInInterfaceBuilder = NO;
return NO; return NO;
} }
/**
* This method is private and is purely for debugging purposes.
*/
- (NSDictionary *)keyMap - (NSDictionary *)keyMap
{ {
return _keyMap; return _keyMap;
} }
/**
* This method returns the class which replaces the class named
* by className. It uses the classes map to do this.
*/
- (Class) replacementClassForClassName: (NSString *)className - (Class) replacementClassForClassName: (NSString *)className
{ {
Class aClass; Class aClass;
@ -1132,6 +1150,15 @@ static BOOL _isInInterfaceBuilder = NO;
} }
@end @end
/**
* NSClassSwapper
*
* This class is used to stand-in for objects which need to be replaced by another object.
* When this class is loaded in the live application, it unarchives and immediately replaces
* itself with the instance of the object requested. This is necessary since IB/Gorm does
* have objects this is used for in palettes, so there is no "live" or actual instance saved
* in the gorm file... only this object as a stand in.
*/
@implementation NSClassSwapper @implementation NSClassSwapper
- (id) initWithObject: (id)object - (id) initWithObject: (id)object
withClassName: (NSString *)className withClassName: (NSString *)className
@ -1146,46 +1173,75 @@ static BOOL _isInInterfaceBuilder = NO;
return self; return self;
} }
/**
* This class method keeps track of whether or not we are operating within IB/Gorm.
* When unarchiving in IB/Gorm some behavior may need to be surpressed for some objects
* or it
*/
+ (void) setIsInInterfaceBuilder: (BOOL)flag + (void) setIsInInterfaceBuilder: (BOOL)flag
{ {
_isInInterfaceBuilder = flag; _isInInterfaceBuilder = flag;
} }
/**
* returns YES, if we are currently in IB/Gorm.
*/
+ (BOOL) isInInterfaceBuilder + (BOOL) isInInterfaceBuilder
{ {
return _isInInterfaceBuilder; return _isInInterfaceBuilder;
} }
/**
* Sets the template represented by temp.
*/
- (void) setTemplate: (id)temp - (void) setTemplate: (id)temp
{ {
ASSIGN(_template, temp); ASSIGN(_template, temp);
} }
/**
* Returns the template.
*/
- (id) template - (id) template
{ {
return _template; return _template;
} }
/**
* Sets the class name.
*/
- (void) setClassName: (NSString *)className - (void) setClassName: (NSString *)className
{ {
ASSIGNCOPY(_className, className); ASSIGNCOPY(_className, className);
} }
/**
* Returns the class name.
*/
- (NSString *)className - (NSString *)className
{ {
return _className; return _className;
} }
/**
* Sets the original class name.
*/
- (void) setOriginalClassName: (NSString *)className - (void) setOriginalClassName: (NSString *)className
{ {
ASSIGNCOPY(_originalClassName, className); ASSIGNCOPY(_originalClassName, className);
} }
/**
* Returns the original class name.
*/
- (NSString *)originalClassName - (NSString *)originalClassName
{ {
return _originalClassName; return _originalClassName;
} }
/**
* Instantiates the real object using className.
*/
- (void) instantiateRealObject: (NSCoder *)coder withClassName: (NSString *)className - (void) instantiateRealObject: (NSCoder *)coder withClassName: (NSString *)className
{ {
Class newClass = nil; Class newClass = nil;
@ -1213,7 +1269,11 @@ static BOOL _isInInterfaceBuilder = NO;
[decoder setDelegate: nil]; // unset the delegate... [decoder setDelegate: nil]; // unset the delegate...
} }
// Delegate method... /**
* This delegate method makes the proper substitution for cellClass
* when the object needs to have it's own cell. An example of this
* is NSSecureTextField/NSSecureTextFieldCell.
*/
- (id) unarchiver: (NSKeyedUnarchiver *)coder - (id) unarchiver: (NSKeyedUnarchiver *)coder
didDecodeObject: (id)obj didDecodeObject: (id)obj
{ {
@ -1246,6 +1306,9 @@ static BOOL _isInInterfaceBuilder = NO;
return result; return result;
} }
/**
* Decode NSClassSwapper.
*/
- (id) initWithCoder: (NSCoder *)coder - (id) initWithCoder: (NSCoder *)coder
{ {
if ([coder allowsKeyedCoding]) if ([coder allowsKeyedCoding])
@ -1273,6 +1336,9 @@ static BOOL _isInInterfaceBuilder = NO;
return _template; return _template;
} }
/**
* Encode NSClassSwapper.
*/
- (void) encodeWithCoder: (NSCoder *)coder - (void) encodeWithCoder: (NSCoder *)coder
{ {
if ([coder allowsKeyedCoding]) if ([coder allowsKeyedCoding])
@ -1289,6 +1355,9 @@ static BOOL _isInInterfaceBuilder = NO;
} }
} }
/**
* Deallocate NSClassSwapper instance.
*/
- (void) dealloc - (void) dealloc
{ {
RELEASE(_className); RELEASE(_className);
@ -1299,14 +1368,26 @@ static BOOL _isInInterfaceBuilder = NO;
@end @end
@implementation NSNibConnector (NibCompatibility) @implementation NSNibConnector (NibCompatibility)
/**
* This method causes the connection to instantiate the objects in it's source
* and destination. The instantiator is the object which holds any custom
* class information which might be needed to do the proprer substitution of
* objects based on the contents of the maps.
*/
- (void) instantiateWithInstantiator: (id<GSInstantiator>)instantiator - (void) instantiateWithInstantiator: (id<GSInstantiator>)instantiator
{ {
_src = [instantiator instantiateObject: _src]; [self setSource: [instantiator instantiateObject: _src]];
_dst = [instantiator instantiateObject: _dst]; [self setDestination: [instantiator instantiateObject: _dst]];
} }
@end @end
@implementation NSNibControlConnector (NibCompatibility) @implementation NSNibControlConnector (NibCompatibility)
/**
* This method overrides the default implementation of instantiate with
* instantiator. It also corrects a common issue in some nib files
* by adding a colon to the end if none was given. It then calls the
* superclass with the corrected label.
*/
- (void) instantiateWithInstantiator: (id<GSInstantiator>)instantiator - (void) instantiateWithInstantiator: (id<GSInstantiator>)instantiator
{ {
NSRange colonRange = [_tag rangeOfString: @":"]; NSRange colonRange = [_tag rangeOfString: @":"];
@ -1322,6 +1403,23 @@ static BOOL _isInInterfaceBuilder = NO;
} }
@end @end
/**
* NSIBObjectData
*
* This class is the container for all of the nib data. It contains several maps.
* The maps are the following:
*
* name -> object (name table)
* object -> name (name table reverse lookup)
* classes -> object (for custom class storage)
* oids -> object (for relating the oid to each object)
* accessibilityOids -> object
*
* The maps are stored in the nib itself as a set of synchronized
* arrays one array containing the keys and the other the values. This is why, in the
* initWithCoder: and encodeWithCoder: methods they are saved as arrays and then
* loaded into NSMapTables.
*/
@implementation NSIBObjectData @implementation NSIBObjectData
/** /**
* Get the values from the map in the same order as the keys. * Get the values from the map in the same order as the keys.
@ -1362,7 +1460,7 @@ static BOOL _isInInterfaceBuilder = NO;
} }
/** /**
* Encode the NSIBObjectData. * Encode the NSIBObjectData container
*/ */
- (void) encodeWithCoder: (NSCoder *)coder - (void) encodeWithCoder: (NSCoder *)coder
{ {
@ -1408,7 +1506,7 @@ static BOOL _isInInterfaceBuilder = NO;
} }
/** /**
* Decode the NSIBObjectData. * Decode the NSIBObjectData container.
*/ */
- (id) initWithCoder: (NSCoder *)coder - (id) initWithCoder: (NSCoder *)coder
{ {
@ -1425,15 +1523,38 @@ static BOOL _isInInterfaceBuilder = NO;
NSArray *accessibilityOidsKeys = nil; NSArray *accessibilityOidsKeys = nil;
NSArray *accessibilityOidsValues = nil; NSArray *accessibilityOidsValues = nil;
//
// Get root, font, framwork and oid.
// Retain objects since NSKeyedUnarchiver autoreleases unarchived objects.
//
ASSIGN(_root, [coder decodeObjectForKey: @"NSRoot"]); ASSIGN(_root, [coder decodeObjectForKey: @"NSRoot"]);
ASSIGN(_visibleWindows,
(NSMutableArray *)[coder decodeObjectForKey: @"NSVisibleWindows"]);
ASSIGN(_accessibilityConnectors,
(NSMutableArray *)[coder decodeObjectForKey: @"NSAccessibilityConnectors"]);
ASSIGN(_fontManager, [coder decodeObjectForKey: @"NSFontManager"]); ASSIGN(_fontManager, [coder decodeObjectForKey: @"NSFontManager"]);
ASSIGN(_framework, [coder decodeObjectForKey: @"NSFramework"]); ASSIGN(_framework, [coder decodeObjectForKey: @"NSFramework"]);
_nextOid = [coder decodeIntForKey: @"NSNextOid"]; _nextOid = [coder decodeIntForKey: @"NSNextOid"];
// get connections.
ASSIGN(_connections, (NSMutableArray *)
[coder decodeObjectForKey: @"NSConnections"]);
ASSIGN(_accessibilityConnectors, (NSMutableArray *)
[coder decodeObjectForKey: @"NSAccessibilityConnectors"]);
// get visible windows
ASSIGN(_visibleWindows, (NSMutableArray *)
[coder decodeObjectForKey: @"NSVisibleWindows"]);
// instantiate the maps..
_classes = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 2);
_names = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 2);
_objects = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 2);
//
// Get the maps. There is no need to retain these,
// since they are going to be placed into the NSMapTable
// structures anyway.
//
nameKeys = (NSArray *) nameKeys = (NSArray *)
[coder decodeObjectForKey: @"NSNamesKeys"]; [coder decodeObjectForKey: @"NSNamesKeys"];
nameValues = (NSArray *) nameValues = (NSArray *)
@ -1442,14 +1563,30 @@ static BOOL _isInInterfaceBuilder = NO;
[coder decodeObjectForKey: @"NSClassesKeys"]; [coder decodeObjectForKey: @"NSClassesKeys"];
classValues = (NSArray *) classValues = (NSArray *)
[coder decodeObjectForKey: @"NSClassesValues"]; [coder decodeObjectForKey: @"NSClassesValues"];
objectsKeys = (NSArray *)
[coder decodeObjectForKey: @"NSObjectsKeys"];
objectsValues = (NSArray *)
[coder decodeObjectForKey: @"NSObjectsValues"];
// Only get this when in the editor... // Fill in the maps...
[self _buildMap: _classes
withKeys: classKeys
andValues: classValues];
[self _buildMap: _names
withKeys: nameKeys
andValues: nameValues];
[self _buildMap: _objects
withKeys: objectsKeys
andValues: objectsValues];
//
// Only get these maps when in the editor. They
// aren't useful outside of it and only waste memory if
// unarchived in the live application.
//
if([NSClassSwapper isInInterfaceBuilder]) if([NSClassSwapper isInInterfaceBuilder])
{ {
objectsKeys = (NSArray *) // Only get these when in the editor...
[coder decodeObjectForKey: @"NSObjectsKeys"];
objectsValues = (NSArray *)
[coder decodeObjectForKey: @"NSObjectsValues"];
oidsKeys = (NSArray *) oidsKeys = (NSArray *)
[coder decodeObjectForKey: @"NSOidsKeys"]; [coder decodeObjectForKey: @"NSOidsKeys"];
oidsValues = (NSArray *) oidsValues = (NSArray *)
@ -1458,46 +1595,19 @@ static BOOL _isInInterfaceBuilder = NO;
[coder decodeObjectForKey: @"NSAccessibilityOidsKeys"]; [coder decodeObjectForKey: @"NSAccessibilityOidsKeys"];
accessibilityOidsValues = (NSArray *) accessibilityOidsValues = (NSArray *)
[coder decodeObjectForKey: @"NSAccessibilityOidsValues"]; [coder decodeObjectForKey: @"NSAccessibilityOidsValues"];
}
// instantiate the maps.. _accessibilityOids = NSCreateMapTable(NSObjectMapKeyCallBacks,
_objects = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2);
NSObjectMapValueCallBacks, 2); _oids = NSCreateMapTable(NSObjectMapKeyCallBacks,
_names = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 2);
NSObjectMapValueCallBacks, 2);
_oids = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 2);
_classes = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 2);
_accessibilityOids = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 2);
// Fill in the maps...
/*
*/
[self _buildMap: _classes
withKeys: classKeys
andValues: classValues];
[self _buildMap: _names
withKeys: nameKeys
andValues: nameValues];
// Only get this when in the editor.
if([NSClassSwapper isInInterfaceBuilder])
{
[self _buildMap: _accessibilityOids [self _buildMap: _accessibilityOids
withKeys: accessibilityOidsKeys withKeys: accessibilityOidsKeys
andValues: accessibilityOidsValues]; andValues: accessibilityOidsValues];
[self _buildMap: _objects
withKeys: objectsKeys
andValues: objectsValues];
[self _buildMap: _oids [self _buildMap: _oids
withKeys: oidsKeys withKeys: oidsKeys
andValues: oidsValues]; andValues: oidsValues];
} }
ASSIGN(_connections, [[coder decodeObjectForKey: @"NSConnections"] mutableCopy]);
// instantiate... // instantiate...
_topLevelObjects = [[NSMutableSet alloc] init]; _topLevelObjects = [[NSMutableSet alloc] init];
} }
@ -1512,7 +1622,7 @@ static BOOL _isInInterfaceBuilder = NO;
} }
/** /**
* Instantiate a new one. * Initialize a new NSIBObjectData.
*/ */
- (id) init - (id) init
{ {
@ -1543,16 +1653,20 @@ static BOOL _isInInterfaceBuilder = NO;
} }
/** /**
* Deallocate. * Deallocate NSIBObjectData.
*/ */
- (void) dealloc - (void) dealloc
{ {
// free the maps. // free the maps.
NSFreeMapTable(_objects); NSFreeMapTable(_objects);
NSFreeMapTable(_names); NSFreeMapTable(_names);
NSFreeMapTable(_oids);
NSFreeMapTable(_classes); NSFreeMapTable(_classes);
NSFreeMapTable(_accessibilityOids); // these are not allocated when not in interface builder.
if([NSClassSwapper isInInterfaceBuilder])
{
NSFreeMapTable(_oids);
NSFreeMapTable(_accessibilityOids);
}
// free other objects. // free other objects.
RELEASE(_accessibilityConnectors); RELEASE(_accessibilityConnectors);
@ -1702,67 +1816,108 @@ static BOOL _isInInterfaceBuilder = NO;
return result; return result;
} }
/**
* Set the root object.
*/
- (void) setRoot: (id) root - (void) setRoot: (id) root
{ {
ASSIGN(_root, root); ASSIGN(_root, root);
} }
/**
* Return the root object.
*/
- (id) root - (id) root
{ {
return _root; return _root;
} }
/**
* Set the value of the next available oid.
*/
- (void) setNextOid: (int)noid - (void) setNextOid: (int)noid
{ {
_nextOid = noid; _nextOid = noid;
} }
/**
* Get the value of the next available oid.
*/
- (int) nextOid - (int) nextOid
{ {
return _nextOid; return _nextOid;
} }
/**
* Connections between objects.
*/
- (NSMutableArray *) connections - (NSMutableArray *) connections
{ {
return _connections; return _connections;
} }
/**
* Set of top level objects.
*/
- (NSMutableSet *) topLevelObjects - (NSMutableSet *) topLevelObjects
{ {
return _topLevelObjects; return _topLevelObjects;
} }
/**
* Names to objects
*/
- (NSMutableDictionary *) nameTable - (NSMutableDictionary *) nameTable
{ {
return nil; return nil;
} }
/**
* Set of all visible windows.
*/
- (NSMutableArray *) visibleWindows - (NSMutableArray *) visibleWindows
{ {
return _visibleWindows; return _visibleWindows;
} }
/**
* Objects to names table.
*/
- (NSMapTable *) objects - (NSMapTable *) objects
{ {
return _objects; return _objects;
} }
/**
* Names to objects table.
*/
- (NSMapTable *) names - (NSMapTable *) names
{ {
return _names; return _names;
} }
/**
* Classes to objects table.
*/
- (NSMapTable *) classes - (NSMapTable *) classes
{ {
return _classes; return _classes;
} }
/**
* Oids to objects table.
*/
- (NSMapTable *) oids - (NSMapTable *) oids
{ {
return _oids; return _oids;
} }
@end @end
/**
* NSButtonImageSource
*
* This class is used by buttons to pull the correct image based on a given state.
*/
@implementation NSButtonImageSource @implementation NSButtonImageSource
- (id) initWithCoder: (NSCoder *)coder - (id) initWithCoder: (NSCoder *)coder
{ {
@ -1795,6 +1950,9 @@ static BOOL _isInInterfaceBuilder = NO;
} }
} }
/**
* Initializes with image name.
*/
- (id) initWithImageNamed: (NSString *)name - (id) initWithImageNamed: (NSString *)name
{ {
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
@ -1804,6 +1962,9 @@ static BOOL _isInInterfaceBuilder = NO;
return self; return self;
} }
/**
* Returns imageName.
*/
- (NSString *)imageName - (NSString *)imageName
{ {
return imageName; return imageName;
@ -1941,13 +2102,26 @@ static BOOL _isInInterfaceBuilder = NO;
@end @end
// ...dummy/placeholder classes... /**
// overridden in NSTableView to be GSTableCornerView, * NSCornerView
// but the class needs to be present to be overridden. *
* Overridden in NSTableView to be GSTableCornerView,
* but the class needs to be present to be overridden.
*
* Currently this is a place-holder class.
*/
@implementation _NSCornerView @implementation _NSCornerView
@end @end
// class needed for nib encoding/decoding by /**
* NSPSMatrix.
*
* This class is needed for nib encoding/decoding by transforms.
* Currently it's only referenced in the NSProgressIndicator,
* as far as I can tell.
*
* Place holder class.
*/
@implementation NSPSMatrix @implementation NSPSMatrix
- (void) encodeWithCoder: (NSCoder *)coder - (void) encodeWithCoder: (NSCoder *)coder
{ {
@ -1956,7 +2130,6 @@ static BOOL _isInInterfaceBuilder = NO;
- (id) initWithCoder: (NSCoder *)coder - (id) initWithCoder: (NSCoder *)coder
{ {
// what's NSPSMatix all about?
// NSLog(@"NSPSMatrix = %@",[(NSKeyedUnarchiver *)coder keyMap]); // NSLog(@"NSPSMatrix = %@",[(NSKeyedUnarchiver *)coder keyMap]);
return self; return self;
} }