Rewrite of top level object handling in NIB/Gorm/Xib loading.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@30070 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2010-03-28 21:33:08 +00:00
parent d1c9ba660b
commit 504a5c2064
8 changed files with 55 additions and 84 deletions

View file

@ -1,3 +1,14 @@
2010-03-28 Fred Kiefer <FredKiefer@gmx.de>
* Headers/AppKit/NSNib.h,
* Source/externs.m: Define new string constants NSNibOwner and NSNibTopLevelObjects.
* Source/NSBundleAdditions.m,
* Source/NSNib.m: Use these constants.
* Source/GSNibLoading.m,
* Source/GSGormLoading.m,
* Source/GSXibLoader.m: Rewrite of top level objects handling to
fit documentations as cited by Wolfgang Lux <wolfgang.lux@gmail.com>.
2010-03-28 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSPasteboard.m (-writeObjects:): Add a return statement

View file

@ -45,6 +45,7 @@
#import <Foundation/NSObject.h>
#import <Foundation/NSZone.h>
#import <AppKit/AppKitDefines.h>
@class NSData;
@class NSDictionary;
@ -54,6 +55,9 @@
@class NSArray;
@class NSMutableArray;
APPKIT_EXPORT NSString *NSNibTopLevelObjects;
APPKIT_EXPORT NSString *NSNibOwner;
@interface NSNib : NSObject <NSCoding>
{
NSData *_nibData;

View file

@ -38,6 +38,7 @@
#import "AppKit/NSApplication.h"
#import "AppKit/NSControl.h"
#import "AppKit/NSMenu.h"
#import "AppKit/NSNib.h"
#import "AppKit/NSNibLoading.h"
#import "AppKit/NSNibConnector.h"
#import "AppKit/NSScreen.h"
@ -156,16 +157,8 @@ static NSString *GSInternalNibItemAddedNotification = @"_GSInternalNibItemAddedN
// Add these objects with there old names as the code expects them
context = AUTORELEASE([context mutableCopyWithZone: [context zone]]);
obj = [context objectForKey: @"NSNibTopLevelObjects"];
if (obj != nil)
{
[(NSMutableDictionary*)context setObject: obj forKey: @"NSTopLevelObjects"];
}
obj = [context objectForKey: @"NSNibOwner"];
if (obj != nil)
{
[(NSMutableDictionary*)context setObject: obj forKey: @"NSOwner"];
}
obj = [context objectForKey: NSNibTopLevelObjects];
obj = [context objectForKey: NSNibOwner];
isAwake = YES;
/*
@ -226,12 +219,11 @@ static NSString *GSInternalNibItemAddedNotification = @"_GSInternalNibItemAddedN
/*
* See if the user has passed in the NSTopLevelObjects key.
* This is an implementation of an undocumented, but commonly used feature
* of nib files to allow the release of the top level objects in the nib
* file.
* See if the user has passed in the NSNibTopLevelObjects key.
* This is an implementation of a commonly used feature to give access to
* all top level objects of a nib file.
*/
obj = [context objectForKey: @"NSTopLevelObjects"];
obj = [context objectForKey: NSNibTopLevelObjects];
if ([obj isKindOfClass: [NSMutableArray class]])
{
topObjects = obj;
@ -250,12 +242,12 @@ static NSString *GSInternalNibItemAddedNotification = @"_GSInternalNibItemAddedN
while ((key = [enumerator nextObject]) != nil)
{
if ([context objectForKey: key] == nil ||
[key isEqualToString: @"NSOwner"]) // we want to send the message to the owner
[key isEqualToString: NSNibOwner]) // we want to send the message to the owner
{
// we don't want to send a message to these menus twice, if they're custom classes.
if ([key isEqualToString: @"NSWindowsMenu"] == NO &&
[key isEqualToString: @"NSServicesMenu"] == NO &&
[key isEqualToString: @"NSTopLevelObjects"] == NO)
[key isEqualToString: NSNibTopLevelObjects] == NO)
{
id o = [nameTable objectForKey: key];
@ -272,30 +264,22 @@ static NSString *GSInternalNibItemAddedNotification = @"_GSInternalNibItemAddedN
* We don't want to retain the owner.
*
* Please note: It is encumbent upon the developer of an application to
* release these objects. Instantiating a window manually or loading in a .gorm
* file are equivalent processes. These objects need to be released in their
* respective controllers. If the developer has used the "NSTopLevelObjects" feature,
* then he will get the objects back in an array which he merely must release in
* order to release the objects held within. GJC
* release these objects. Instantiating a window manually or loading in a .gorm
* file are equivalent processes. These objects need to be released in their
* respective controllers. If the developer has used the NSNibTopLevelObjects feature,
* then she will get the objects back in an array. She will will have to first release
* all the objects in the array and then the array itself in order to release the
* objects held within.
*/
if ([key isEqualToString: @"NSOwner"] == NO)
if ([key isEqualToString: NSNibOwner] == NO)
{
if ([topLevelObjects containsObject: o]) // anything already designated a top level item..
{
if (topObjects == nil)
{
// It is expected, if the NSTopLevelObjects key is not passed in,
// that the user has opted to either allow these objects to leak or
// to release them explicitly.
RETAIN(o);
}
else
{
// We don't want to do the extra retain if the items are added to the
// array, since the array will do the retain for us. When the array
// is released, the top level objects should be released as well.
[topObjects addObject: o];
}
[topObjects addObject: o];
// All top level objects (that are not retained and
// released by other nib objects) must be released by
// the caller to avoid leaking.
RETAIN(o);
}
}
}

View file

@ -62,6 +62,7 @@
#import "AppKit/NSImage.h"
#import "AppKit/NSMenuItem.h"
#import "AppKit/NSMenuView.h"
#import "AppKit/NSNib.h"
#import "AppKit/NSScreen.h"
#import "AppKit/NSSound.h"
#import "GNUstepGUI/GSInstantiator.h"
@ -1909,15 +1910,10 @@ static BOOL _isInInterfaceBuilder = NO;
// Object is top level if it isn't the owner but points to it.
if ((v == owner || v == _root) && (obj != owner) && (obj != _root))
{
if (topLevelObjects == nil)
{
// When there is no top level object array, just retain these objects
RETAIN(obj);
}
else
{
[topLevelObjects addObject: obj];
}
[topLevelObjects addObject: obj];
// All top level objects must be released by
// the caller to avoid leaking.
RETAIN(obj);
}
// awaken the object.
@ -1950,19 +1946,8 @@ static BOOL _isInInterfaceBuilder = NO;
*/
- (void) awakeWithContext: (NSDictionary *)context
{
NSMutableArray *tlo = [context objectForKey: @"NSTopLevelObjects"];
id owner = [context objectForKey: @"NSOwner"];
// get using the alternate names.
if (tlo == nil)
{
tlo = [context objectForKey: @"NSNibTopLevelObjects"];
}
if (owner == nil)
{
owner = [context objectForKey: @"NSNibOwner"];
}
NSMutableArray *tlo = [context objectForKey: NSNibTopLevelObjects];
id owner = [context objectForKey: NSNibOwner];
// instantiate...
[self nibInstantiateWithOwner: owner topLevelObjects: tlo];

View file

@ -38,6 +38,7 @@
#import <GNUstepBase/GSMime.h>
#import "AppKit/NSApplication.h"
#import "AppKit/NSNib.h"
#import "AppKit/NSNibLoading.h"
#import "GNUstepGUI/GSModelLoaderFactory.h"
#import "GNUstepGUI/GSNibLoading.h"
@ -576,19 +577,8 @@
NSEnumerator *en;
id obj;
IBObjectContainer *objects;
NSMutableArray *topLevelObjects = [context objectForKey: @"NSTopLevelObjects"];
id owner = [context objectForKey: @"NSOwner"];
// get using the alternate names.
if (topLevelObjects == nil)
{
topLevelObjects = [context objectForKey: @"NSNibTopLevelObjects"];
}
if (owner == nil)
{
owner = [context objectForKey: @"NSNibOwner"];
}
NSMutableArray *topLevelObjects = [context objectForKey: NSNibTopLevelObjects];
//id owner = [context objectForKey: NSNibOwner];
objects = [data objectForKey: @"IBDocument.Objects"];
[objects nibInstantiate];
@ -602,15 +592,8 @@
if ([obj respondsToSelector: @selector(nibInstantiate)])
{
obj = [obj nibInstantiate];
if (topLevelObjects == nil)
{
// When there is no top level object array, just retain these objects
RETAIN(obj);
}
else
{
[topLevelObjects addObject: obj];
}
[topLevelObjects addObject: obj];
RETAIN(obj);
}
// instantiate all windows and fill in the top level array.

View file

@ -249,7 +249,7 @@
{
return NO;
}
table = [NSDictionary dictionaryWithObject: owner forKey: @"NSNibOwner"];
table = [NSDictionary dictionaryWithObject: owner forKey: NSNibOwner];
/*
* First look for the NIB in the bundle corresponding to the owning class,

View file

@ -178,12 +178,12 @@
NSMutableDictionary *externalNameTable = [NSMutableDictionary dictionary];
// add the necessary things to the table...
[externalNameTable setObject: owner forKey: @"NSNibOwner"];
[externalNameTable setObject: owner forKey: NSNibOwner];
if (topLevelObjects != 0)
{
*topLevelObjects = [NSMutableArray array];
[externalNameTable setObject: *topLevelObjects forKey: @"NSNibTopLevelObjects"];
[externalNameTable setObject: *topLevelObjects forKey: NSNibTopLevelObjects];
}
return [self instantiateNibWithExternalNameTable: externalNameTable];

View file

@ -659,6 +659,10 @@ id NSNoSelectionMarker = @"NSNoSelectionMarker";
id NSNotApplicableMarker = @"NSNotApplicableMarker";
// NSNib
NSString *NSNibTopLevelObjects = @"NSTopLevelObjects";
NSString *NSNibOwner = @"NSOwner";
extern void __objc_gui_force_linking (void);
void