mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-22 13:10:59 +00:00
Clean up the old XIB loading code.
This commit is contained in:
parent
46ea0fb36d
commit
bc7c0262c5
5 changed files with 1053 additions and 1029 deletions
|
@ -1,3 +1,10 @@
|
|||
2020-01-19 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Source/GSXibKeyedUnarchiver.m: Remove references of XIB 5.
|
||||
* Headers/Additions/GNUstepGUI/GSNibLoading.h: Add one method definition.
|
||||
* Source/GSXibLoader.m,
|
||||
* Source/GSXibLoading.m: Move helper classes to the correct file.
|
||||
|
||||
2020-01-19 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Source/GSXib5KeyedUnarchiver.m: Handle dictionary elements correctly.
|
||||
|
|
|
@ -220,6 +220,7 @@ typedef struct _GSWindowTemplateFlags
|
|||
- (void) setExtension: (NSString *)ext;
|
||||
- (NSString *)extension;
|
||||
- (void) setRealObject: (id)obj;
|
||||
- (id) realObject;
|
||||
@end
|
||||
|
||||
@interface NSCustomView : NSView <GSNibLoading>
|
||||
|
|
|
@ -1,29 +1,32 @@
|
|||
/** <title>GSXibKeyedUnarchiver.m</title>
|
||||
|
||||
|
||||
<abstract>
|
||||
These are templates for use with OSX XIB 5 files. These classes are the
|
||||
templates and other things which are needed for reading XIB 5 files.
|
||||
These are templates for use with OSX XIB files. These classes are the
|
||||
templates and other things which are needed for reading XIB files.
|
||||
</abstract>
|
||||
|
||||
Copyright (C) 2005, 2017 Free Software Foundation, Inc.
|
||||
|
||||
|
||||
Copyright (C) 2010, 2012, 2017 Free Software Foundation, Inc.
|
||||
|
||||
File created by Marcian Lytwyn on 12/30/16 from original code by:
|
||||
|
||||
|
||||
Author: Fred Kiefer <FredKiefer@gmx.de>
|
||||
Date: March 2010
|
||||
|
||||
Author: Gregory John Casamento
|
||||
Date: 2003, 2005
|
||||
|
||||
Date: 2012
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
|
||||
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 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.
|
||||
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
|
@ -39,167 +42,160 @@
|
|||
|
||||
- (NSData *) _preProcessXib: (NSData *)data
|
||||
{
|
||||
NSData *result = nil;
|
||||
NSData *result = data;
|
||||
|
||||
#if GNUSTEP_BASE_HAVE_LIBXML
|
||||
NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data
|
||||
options:0
|
||||
error:NULL];
|
||||
result = data;
|
||||
|
||||
if (document == nil)
|
||||
{
|
||||
NSLog(@"%s:DOCUMENT IS NIL: %@\n", __PRETTY_FUNCTION__, document);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Test to see if this is an Xcode 5 XIB...
|
||||
NSArray *documentNodes = [document nodesForXPath:@"/document"
|
||||
error:NULL];
|
||||
if ([documentNodes count] > 0)
|
||||
{
|
||||
NSLog(@"Unsupported... This is an XCode 5 XIB file.");
|
||||
return nil;
|
||||
}
|
||||
NSArray *customClassNodes = [document nodesForXPath:@"//dictionary[@key=\"flattenedProperties\"]/"
|
||||
@"string[contains(@key,\"CustomClassName\")]"
|
||||
error:NULL];
|
||||
NSMutableDictionary *customClassDict = [NSMutableDictionary dictionary];
|
||||
if (customClassNodes)
|
||||
{
|
||||
NSDebugLLog(@"PREXIB", @"%s:customClassNodes: %@\n", __PRETTY_FUNCTION__, customClassNodes);
|
||||
|
||||
// Replace the NSXMLNodes with a dictionary...
|
||||
NSInteger index = 0;
|
||||
for (index = 0; index < [customClassNodes count]; ++index)
|
||||
{
|
||||
id node = [customClassNodes objectAtIndex:index];
|
||||
if ([node isMemberOfClass:[NSXMLElement class]])
|
||||
{
|
||||
NSString *key = [[node attributeForName:@"key"] stringValue];
|
||||
if ([key rangeOfString:@"CustomClassName"].location != NSNotFound)
|
||||
{
|
||||
[customClassDict setObject:[node stringValue] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSArray *customClassNodes = [document nodesForXPath:@"//dictionary[@key=\"flattenedProperties\"]/"
|
||||
@"string[contains(@key,\"CustomClassName\")]"
|
||||
error:NULL];
|
||||
NSMutableDictionary *customClassDict = [NSMutableDictionary dictionary];
|
||||
if (customClassNodes)
|
||||
{
|
||||
NSDebugLLog(@"PREXIB", @"%s:customClassNodes: %@\n", __PRETTY_FUNCTION__, customClassNodes);
|
||||
|
||||
// Replace the NSXMLNodes with a dictionary...
|
||||
NSInteger index = 0;
|
||||
for (index = 0; index < [customClassNodes count]; ++index)
|
||||
{
|
||||
id node = [customClassNodes objectAtIndex:index];
|
||||
if ([node isMemberOfClass:[NSXMLElement class]])
|
||||
{
|
||||
NSString *key = [[node attributeForName:@"key"] stringValue];
|
||||
if ([key rangeOfString:@"CustomClassName"].location != NSNotFound)
|
||||
{
|
||||
[customClassDict setObject:[node stringValue] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSArray *flatProps = [document nodesForXPath:@"//object[@key=\"flattenedProperties\"]" error:NULL];
|
||||
if ([flatProps count] == 1)
|
||||
{
|
||||
NSInteger index = 0;
|
||||
NSArray *xmlKeys = [[flatProps objectAtIndex:0] nodesForXPath:@"//object[@key=\"flattenedProperties\"]/object[@key=\"dict.sortedKeys\"]/*" error:NULL];
|
||||
NSArray *xmlObjs = [[flatProps objectAtIndex:0] nodesForXPath:@"//object[@key=\"flattenedProperties\"]/object[@key=\"dict.values\"]/*" error:NULL];
|
||||
if ([xmlKeys count] != [xmlObjs count])
|
||||
{
|
||||
NSLog(@"%s:keys to objs count mismatch - keys: %d objs: %d\n", __PRETTY_FUNCTION__,
|
||||
(int)[xmlKeys count], (int)[xmlObjs count]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (index = 0; index < [xmlKeys count]; ++index)
|
||||
{
|
||||
id key = [[xmlKeys objectAtIndex:index] stringValue];
|
||||
if ([key rangeOfString:@"CustomClassName"].location != NSNotFound)
|
||||
{
|
||||
// NSString *obj = [[xmlObjs objectAtIndex:index] stringValue];
|
||||
[customClassDict setObject:[[xmlObjs objectAtIndex:index] stringValue] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSDebugLLog(@"PREXIB", @"%s:customClassDict: %@\n", __PRETTY_FUNCTION__, customClassDict);
|
||||
|
||||
if ([customClassDict count] > 0)
|
||||
{
|
||||
NSArray *objectRecords = nil;
|
||||
NSEnumerator *en = [[customClassDict allKeys] objectEnumerator];
|
||||
NSString *key = nil;
|
||||
|
||||
while ((key = [en nextObject]) != nil)
|
||||
{
|
||||
NSString *keyValue = [key stringByReplacingOccurrencesOfString:@".CustomClassName" withString:@""];
|
||||
NSString *className = [customClassDict objectForKey: key];
|
||||
NSString *objectRecordXpath = nil;
|
||||
|
||||
objectRecordXpath = [NSString stringWithFormat: @"//object[@class=\"IBObjectRecord\"]/"
|
||||
@"int[@key=\"objectID\"][text()=\"%@\"]/../reference",
|
||||
keyValue];
|
||||
|
||||
objectRecords = [document nodesForXPath: objectRecordXpath error: NULL];
|
||||
|
||||
if (objectRecords == nil)
|
||||
{
|
||||
// If that didn't work then it could be a 4.6+ XIB...
|
||||
objectRecordXpath = [NSString stringWithFormat: @"//object[@class=\"IBObjectRecord\"]/"
|
||||
@"string[@key=\"id\"][text()=\"%@\"]/../reference",
|
||||
keyValue];
|
||||
objectRecords = [document nodesForXPath: objectRecordXpath error: NULL];
|
||||
}
|
||||
|
||||
NSString *refId = nil;
|
||||
if ([objectRecords count] > 0)
|
||||
{
|
||||
id record = nil;
|
||||
NSEnumerator *oen = [objectRecords objectEnumerator];
|
||||
while ((record = [oen nextObject]) != nil)
|
||||
{
|
||||
if ([record isMemberOfClass:[NSXMLElement class]])
|
||||
{
|
||||
if([[[record attributeForName:@"key"] stringValue] isEqualToString:@"object"])
|
||||
{
|
||||
NSArray *classNodes = nil;
|
||||
id classNode = nil;
|
||||
NSString *refXpath = nil;
|
||||
|
||||
refId = [[record attributeForName:@"ref"] stringValue];
|
||||
refXpath = [NSString stringWithFormat:@"//object[@id=\"%@\"]",refId];
|
||||
classNodes = [document nodesForXPath:refXpath
|
||||
error:NULL];
|
||||
if([classNodes count] > 0)
|
||||
{
|
||||
id classAttr = nil;
|
||||
Class cls = NSClassFromString(className);
|
||||
|
||||
classNode = [classNodes objectAtIndex:0];
|
||||
classAttr = [classNode attributeForName:@"class"];
|
||||
[classAttr setStringValue:className];
|
||||
|
||||
if (cls != nil)
|
||||
{
|
||||
if ([cls respondsToSelector:@selector(cellClass)])
|
||||
{
|
||||
NSArray *cellNodes = nil;
|
||||
id cellNode = nil;
|
||||
id cellClass = [cls cellClass];
|
||||
NSString *cellXpath = [NSString stringWithFormat:@"//object[@id=\"%@\"]/object[@key=\"NSCell\"]",refId];
|
||||
cellNodes = [document nodesForXPath:cellXpath
|
||||
error:NULL];
|
||||
if ([cellNodes count] > 0)
|
||||
{
|
||||
NSString *cellClassString = NSStringFromClass(cellClass);
|
||||
id cellAttr = nil;
|
||||
cellNode = [cellNodes objectAtIndex:0];
|
||||
cellAttr = [cellNode attributeForName:@"class"];
|
||||
[cellAttr setStringValue:cellClassString];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = [document XMLData];
|
||||
RELEASE(document);
|
||||
}
|
||||
{
|
||||
NSArray *flatProps = [document nodesForXPath:@"//object[@key=\"flattenedProperties\"]" error:NULL];
|
||||
if ([flatProps count] == 1)
|
||||
{
|
||||
NSInteger index = 0;
|
||||
NSArray *xmlKeys = [[flatProps objectAtIndex:0] nodesForXPath:
|
||||
@"//object[@key=\"flattenedProperties\"]/object[@key=\"dict.sortedKeys\"]/*" error:NULL];
|
||||
NSArray *xmlObjs = [[flatProps objectAtIndex:0] nodesForXPath:
|
||||
@"//object[@key=\"flattenedProperties\"]/object[@key=\"dict.values\"]/*" error:NULL];
|
||||
if ([xmlKeys count] != [xmlObjs count])
|
||||
{
|
||||
NSLog(@"%s:keys to objs count mismatch - keys: %d objs: %d\n", __PRETTY_FUNCTION__,
|
||||
(int)[xmlKeys count], (int)[xmlObjs count]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (index = 0; index < [xmlKeys count]; ++index)
|
||||
{
|
||||
id key = [[xmlKeys objectAtIndex:index] stringValue];
|
||||
if ([key rangeOfString:@"CustomClassName"].location != NSNotFound)
|
||||
{
|
||||
// NSString *obj = [[xmlObjs objectAtIndex:index] stringValue];
|
||||
[customClassDict setObject:[[xmlObjs objectAtIndex:index] stringValue] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSDebugLLog(@"PREXIB", @"%s:customClassDict: %@\n", __PRETTY_FUNCTION__, customClassDict);
|
||||
|
||||
if ([customClassDict count] > 0)
|
||||
{
|
||||
NSArray *objectRecords = nil;
|
||||
NSEnumerator *en = [[customClassDict allKeys] objectEnumerator];
|
||||
NSString *key = nil;
|
||||
|
||||
while ((key = [en nextObject]) != nil)
|
||||
{
|
||||
NSString *keyValue = [key stringByReplacingOccurrencesOfString:@".CustomClassName" withString:@""];
|
||||
NSString *className = [customClassDict objectForKey: key];
|
||||
NSString *objectRecordXpath = nil;
|
||||
|
||||
objectRecordXpath = [NSString stringWithFormat: @"//object[@class=\"IBObjectRecord\"]/"
|
||||
@"int[@key=\"objectID\"][text()=\"%@\"]/../reference",
|
||||
keyValue];
|
||||
|
||||
objectRecords = [document nodesForXPath: objectRecordXpath error: NULL];
|
||||
|
||||
if (objectRecords == nil)
|
||||
{
|
||||
// If that didn't work then it could be a 4.6+ XIB...
|
||||
objectRecordXpath = [NSString stringWithFormat: @"//object[@class=\"IBObjectRecord\"]/"
|
||||
@"string[@key=\"id\"][text()=\"%@\"]/../reference",
|
||||
keyValue];
|
||||
objectRecords = [document nodesForXPath: objectRecordXpath error: NULL];
|
||||
}
|
||||
|
||||
NSString *refId = nil;
|
||||
if ([objectRecords count] > 0)
|
||||
{
|
||||
id record = nil;
|
||||
NSEnumerator *oen = [objectRecords objectEnumerator];
|
||||
while ((record = [oen nextObject]) != nil)
|
||||
{
|
||||
if ([record isMemberOfClass:[NSXMLElement class]])
|
||||
{
|
||||
if([[[record attributeForName:@"key"] stringValue] isEqualToString:@"object"])
|
||||
{
|
||||
NSArray *classNodes = nil;
|
||||
id classNode = nil;
|
||||
NSString *refXpath = nil;
|
||||
|
||||
refId = [[record attributeForName:@"ref"] stringValue];
|
||||
refXpath = [NSString stringWithFormat:@"//object[@id=\"%@\"]",refId];
|
||||
classNodes = [document nodesForXPath:refXpath
|
||||
error:NULL];
|
||||
if([classNodes count] > 0)
|
||||
{
|
||||
id classAttr = nil;
|
||||
Class cls = NSClassFromString(className);
|
||||
|
||||
classNode = [classNodes objectAtIndex:0];
|
||||
classAttr = [classNode attributeForName:@"class"];
|
||||
[classAttr setStringValue:className];
|
||||
|
||||
if (cls != nil)
|
||||
{
|
||||
if ([cls respondsToSelector:@selector(cellClass)])
|
||||
{
|
||||
NSArray *cellNodes = nil;
|
||||
id cellNode = nil;
|
||||
id cellClass = [cls cellClass];
|
||||
NSString *cellXpath = [NSString stringWithFormat:
|
||||
@"//object[@id=\"%@\"]/object[@key=\"NSCell\"]",refId];
|
||||
cellNodes = [document nodesForXPath:cellXpath
|
||||
error:NULL];
|
||||
if ([cellNodes count] > 0)
|
||||
{
|
||||
NSString *cellClassString = NSStringFromClass(cellClass);
|
||||
id cellAttr = nil;
|
||||
cellNode = [cellNodes objectAtIndex:0];
|
||||
cellAttr = [cellNode attributeForName:@"class"];
|
||||
[cellAttr setStringValue:cellClassString];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = [document XMLData];
|
||||
RELEASE(document);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
|
@ -235,7 +231,7 @@
|
|||
|
||||
theParser = [[NSXMLParser alloc] initWithData: theData];
|
||||
[theParser setDelegate: self];
|
||||
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
// Parse the XML data
|
||||
|
@ -249,7 +245,7 @@
|
|||
NS_ENDHANDLER
|
||||
|
||||
DESTROY(theParser);
|
||||
#endif
|
||||
#endif
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -405,7 +401,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
// pop
|
||||
currentElement = last;
|
||||
|
||||
|
||||
if (r != o)
|
||||
{
|
||||
[delegate unarchiver: self
|
||||
|
@ -443,7 +439,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
// Balance the retain above
|
||||
RELEASE(o);
|
||||
|
||||
|
||||
if (objID != nil)
|
||||
{
|
||||
NSDebugLLog(@"XIB", @"decoded object %@ for id %@", o, objID);
|
||||
|
@ -454,7 +450,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
/*
|
||||
This method is a copy of decodeObjectForXib:forClassName:withKey:
|
||||
The only difference being in the way we decode the object and the
|
||||
The only difference being in the way we decode the object and the
|
||||
missing context switch.
|
||||
*/
|
||||
- (id) decodeDictionaryForXib: (GSXibElement*)element
|
||||
|
@ -508,7 +504,7 @@ didStartElement: (NSString*)elementName
|
|||
}
|
||||
// Balance the retain above
|
||||
RELEASE(o);
|
||||
|
||||
|
||||
if (objID != nil)
|
||||
{
|
||||
NSDebugLLog(@"XIB", @"decoded object %@ for id %@", o, objID);
|
||||
|
@ -555,7 +551,7 @@ didStartElement: (NSString*)elementName
|
|||
{
|
||||
NSData *d = [[NSData alloc] initWithBase64EncodedString: new
|
||||
options: NSDataBase64DecodingIgnoreUnknownCharacters];
|
||||
new = AUTORELEASE([[NSString alloc] initWithData: d
|
||||
new = AUTORELEASE([[NSString alloc] initWithData: d
|
||||
encoding: NSUTF8StringEncoding]);
|
||||
RELEASE(d);
|
||||
}
|
||||
|
@ -566,7 +562,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"int" isEqualToString: elementName])
|
||||
|
@ -575,7 +571,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"double" isEqualToString: elementName])
|
||||
|
@ -584,7 +580,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"bool" isEqualToString: elementName])
|
||||
|
@ -593,7 +589,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"integer" isEqualToString: elementName])
|
||||
|
@ -603,7 +599,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"real" isEqualToString: elementName])
|
||||
|
@ -613,7 +609,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"boolean" isEqualToString: elementName])
|
||||
|
@ -623,37 +619,37 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"point" isEqualToString: elementName])
|
||||
{
|
||||
NSPoint point = [self decodePointForKey: [element attributeForKey: @"key"]];
|
||||
id new = [NSValue valueWithPoint: point];
|
||||
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"size" isEqualToString: elementName])
|
||||
{
|
||||
NSSize size = [self decodeSizeForKey: [element attributeForKey: @"key"]];
|
||||
id new = [NSValue valueWithSize: size];
|
||||
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"rect" isEqualToString: elementName])
|
||||
{
|
||||
NSRect rect = [self decodeRectForKey: [element attributeForKey: @"key"]];
|
||||
id new = [NSValue valueWithRect: rect];
|
||||
|
||||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"reference" isEqualToString: elementName])
|
||||
|
@ -693,7 +689,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"bytes" isEqualToString: elementName])
|
||||
|
@ -703,7 +699,7 @@ didStartElement: (NSString*)elementName
|
|||
|
||||
if (objID != nil)
|
||||
[decoded setObject: new forKey: objID];
|
||||
|
||||
|
||||
return new;
|
||||
}
|
||||
else if ([@"array" isEqualToString: elementName])
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
#import <Foundation/NSXMLDocument.h>
|
||||
|
||||
#import "AppKit/NSApplication.h"
|
||||
#import "AppKit/NSMenu.h"
|
||||
#import "AppKit/NSNib.h"
|
||||
#import "AppKit/NSNibLoading.h"
|
||||
#import "GNUstepGUI/GSModelLoaderFactory.h"
|
||||
#import "GNUstepGUI/GSNibLoading.h"
|
||||
#import "GNUstepGUI/GSXibLoading.h"
|
||||
|
@ -54,16 +54,6 @@
|
|||
- (BOOL) _isMainMenu;
|
||||
@end
|
||||
|
||||
@interface NSCustomObject (NibCompatibility)
|
||||
- (id) realObject;
|
||||
- (void) setRealObject: (id)obj;
|
||||
- (NSString *)className;
|
||||
@end
|
||||
|
||||
@interface NSNibConnector (NibCompatibility)
|
||||
- (id) nibInstantiate;
|
||||
@end
|
||||
|
||||
@implementation NSMenu (XibCompatibility)
|
||||
|
||||
- (BOOL) _isMainMenu
|
||||
|
@ -75,840 +65,6 @@
|
|||
|
||||
@end
|
||||
|
||||
@implementation FirstResponder
|
||||
|
||||
+ (id) allocWithZone: (NSZone*)zone
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBClassDescriptionSource
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"majorKey"])
|
||||
{
|
||||
ASSIGN(majorKey, [coder decodeObjectForKey: @"majorKey"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"minorKey"])
|
||||
{
|
||||
ASSIGN(minorKey, [coder decodeObjectForKey: @"minorKey"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(majorKey);
|
||||
DESTROY(minorKey);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBPartialClassDescription
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"className"])
|
||||
{
|
||||
ASSIGN(className, [coder decodeObjectForKey: @"className"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"superclassName"])
|
||||
{
|
||||
ASSIGN(superclassName, [coder decodeObjectForKey: @"superclassName"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"actions"])
|
||||
{
|
||||
ASSIGN(actions, [coder decodeObjectForKey: @"actions"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"outlets"])
|
||||
{
|
||||
ASSIGN(outlets, [coder decodeObjectForKey: @"outlets"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"sourceIdentifier"])
|
||||
{
|
||||
ASSIGN(sourceIdentifier, [coder decodeObjectForKey: @"sourceIdentifier"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(className);
|
||||
DESTROY(superclassName);
|
||||
DESTROY(actions);
|
||||
DESTROY(outlets);
|
||||
DESTROY(sourceIdentifier);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBClassDescriber
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"referencedPartialClassDescriptions"])
|
||||
{
|
||||
ASSIGN(referencedPartialClassDescriptions, [coder decodeObjectForKey: @"referencedPartialClassDescriptions"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(referencedPartialClassDescriptions);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBConnection
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"label"])
|
||||
{
|
||||
ASSIGN(label, [coder decodeObjectForKey: @"label"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"source"])
|
||||
{
|
||||
ASSIGN(source, [coder decodeObjectForKey: @"source"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"destination"])
|
||||
{
|
||||
ASSIGN(destination, [coder decodeObjectForKey: @"destination"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(label);
|
||||
DESTROY(source);
|
||||
DESTROY(destination);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString*) label
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
- (id) source
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
- (id) destination
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
|
||||
- (NSNibConnector*) nibConnector
|
||||
{
|
||||
NSString *tag = [self label];
|
||||
NSRange colonRange = [tag rangeOfString: @":"];
|
||||
NSUInteger location = colonRange.location;
|
||||
NSNibConnector *result = nil;
|
||||
|
||||
if (location == NSNotFound)
|
||||
{
|
||||
result = [[NSNibOutletConnector alloc] init];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [[NSNibControlConnector alloc] init];
|
||||
}
|
||||
|
||||
[result setDestination: [self destination]];
|
||||
[result setSource: [self source]];
|
||||
[result setLabel: [self label]];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString*) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@ - label: %@, source: %@, destination: %@",
|
||||
[super description], label, NSStringFromClass([source class]),
|
||||
NSStringFromClass([destination class])];
|
||||
}
|
||||
|
||||
- (id) nibInstantiate
|
||||
{
|
||||
if ([source respondsToSelector: @selector(nibInstantiate)])
|
||||
{
|
||||
ASSIGN(source, [source nibInstantiate]);
|
||||
}
|
||||
if ([destination respondsToSelector: @selector(nibInstantiate)])
|
||||
{
|
||||
ASSIGN(destination, [destination nibInstantiate]);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBActionConnection
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
SEL sel = NSSelectorFromString(label);
|
||||
|
||||
[destination setTarget: source];
|
||||
[destination setAction: sel];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBOutletConnection
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
NS_DURING
|
||||
{
|
||||
if (source != nil)
|
||||
{
|
||||
NSString *selName;
|
||||
SEL sel;
|
||||
|
||||
selName = [NSString stringWithFormat: @"set%@%@:",
|
||||
[[label substringToIndex: 1] uppercaseString],
|
||||
[label substringFromIndex: 1]];
|
||||
sel = NSSelectorFromString(selName);
|
||||
|
||||
if (sel && [source respondsToSelector: sel])
|
||||
{
|
||||
[source performSelector: sel withObject: destination];
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We cannot use the KVC mechanism here, as this would always retain _dst
|
||||
* and it could also affect _setXXX methods and _XXX ivars that aren't
|
||||
* affected by the Cocoa code.
|
||||
*/
|
||||
const char *name = [label cString];
|
||||
Class class = object_getClass(source);
|
||||
Ivar ivar = class_getInstanceVariable(class, name);
|
||||
|
||||
if (ivar != 0)
|
||||
{
|
||||
object_setIvar(source, ivar, destination);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSWarnMLog(@"class '%@' has no instance var named: %@", NSStringFromClass(class), label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSLog(@"Error while establishing connection %@: %@",self,[localException reason]);
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBBindingConnection
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(connector);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
if (self == nil)
|
||||
return nil;
|
||||
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"connector"])
|
||||
{
|
||||
ASSIGN(connector, [coder decodeObjectForKey: @"connector"]);
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) nibInstantiate
|
||||
{
|
||||
[connector nibInstantiate];
|
||||
return [super nibInstantiate];
|
||||
}
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
[connector establishConnection];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBConnectionRecord
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"connection"])
|
||||
{
|
||||
ASSIGN(connection, [coder decodeObjectForKey: @"connection"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *format = [NSString stringWithFormat:@"%s:Can't decode %@ without a connection ID",
|
||||
__PRETTY_FUNCTION__,
|
||||
NSStringFromClass([self class])];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@", format];
|
||||
}
|
||||
|
||||
// Load the connection ID....
|
||||
if ([coder containsValueForKey: @"connectionID"])
|
||||
{
|
||||
// PRE-4.6 XIBs....
|
||||
connectionID = [coder decodeIntForKey: @"connectionID"];
|
||||
}
|
||||
else if ([coder containsValueForKey: @"id"])
|
||||
{
|
||||
// 4.6+ XIBs....
|
||||
NSString *string = [coder decodeObjectForKey: @"id"];
|
||||
|
||||
if (string && [string isKindOfClass:[NSString class]] && [string length])
|
||||
{
|
||||
connectionID = [string intValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *format = [NSString stringWithFormat:@"%s:class: %@ - connection ID is missing or zero!",
|
||||
__PRETTY_FUNCTION__, NSStringFromClass([self class])];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@", format];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *format = [NSString stringWithFormat:@"%s:Can't decode %@ without a connection ID",
|
||||
__PRETTY_FUNCTION__,
|
||||
NSStringFromClass([self class])];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@", format];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(connection);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (IBConnection*) connection
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
- (id) nibInstantiate
|
||||
{
|
||||
ASSIGN(connection, [connection nibInstantiate]);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
[connection establishConnection];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBToolTipAttribute
|
||||
|
||||
- (NSString*) toolTip
|
||||
{
|
||||
return toolTip;
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"name"])
|
||||
{
|
||||
ASSIGN(name, [coder decodeObjectForKey: @"name"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"object"])
|
||||
{
|
||||
ASSIGN(object, [coder decodeObjectForKey: @"object"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"toolTip"])
|
||||
{
|
||||
ASSIGN(toolTip, [coder decodeObjectForKey: @"toolTip"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(name);
|
||||
DESTROY(object);
|
||||
DESTROY(toolTip);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBInitialTabViewItemAttribute
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"name"])
|
||||
{
|
||||
ASSIGN(name, [coder decodeObjectForKey: @"name"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"object"])
|
||||
{
|
||||
ASSIGN(object, [coder decodeObjectForKey: @"object"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"initialTabViewItem"])
|
||||
{
|
||||
ASSIGN(initialTabViewItem, [coder decodeObjectForKey: @"initialTabViewItem"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(name);
|
||||
DESTROY(object);
|
||||
DESTROY(initialTabViewItem);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBObjectRecord
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"objectID"])
|
||||
{
|
||||
// PRE-4.6 XIBs....
|
||||
objectID = [coder decodeObjectForKey: @"objectID"];
|
||||
}
|
||||
else if ([coder containsValueForKey: @"id"])
|
||||
{
|
||||
// 4.6+ XIBs....
|
||||
objectID = [coder decodeObjectForKey: @"id"];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cannot process without object ID...
|
||||
NSString *format = [NSString stringWithFormat:@"%s:Can't decode %@ without an object ID",
|
||||
__PRETTY_FUNCTION__,
|
||||
NSStringFromClass([self class])];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@", format];
|
||||
}
|
||||
|
||||
if ([coder containsValueForKey: @"object"])
|
||||
{
|
||||
ASSIGN(object, [coder decodeObjectForKey: @"object"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"children"])
|
||||
{
|
||||
ASSIGN(children, [coder decodeObjectForKey: @"children"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"parent"])
|
||||
{
|
||||
ASSIGN(parent, [coder decodeObjectForKey: @"parent"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(object);
|
||||
DESTROY(children);
|
||||
DESTROY(parent);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) object
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
- (id) parent
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
- (id) objectID
|
||||
{
|
||||
return objectID;
|
||||
}
|
||||
|
||||
- (NSString *) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"<%@, %@, %@, %p>",
|
||||
[self className],
|
||||
object,
|
||||
parent,
|
||||
objectID];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBMutableOrderedSet
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"orderedObjects"])
|
||||
{
|
||||
ASSIGN(orderedObjects, [coder decodeObjectForKey: @"orderedObjects"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(orderedObjects);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSArray*) orderedObjects
|
||||
{
|
||||
return orderedObjects;
|
||||
}
|
||||
|
||||
- (id) objectWithObjectID: (id)objID
|
||||
{
|
||||
NSEnumerator *en;
|
||||
IBObjectRecord *obj;
|
||||
|
||||
en = [orderedObjects objectEnumerator];
|
||||
while ((obj = [en nextObject]) != nil)
|
||||
{
|
||||
if ([[obj objectID] isEqual:objID])
|
||||
{
|
||||
return [obj object];
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBObjectContainer
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"sourceID"])
|
||||
{
|
||||
ASSIGN(sourceID, [coder decodeObjectForKey: @"sourceID"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"maxID"])
|
||||
{
|
||||
maxID = [coder decodeIntForKey: @"maxID"];
|
||||
}
|
||||
if ([coder containsValueForKey: @"flattenedProperties"])
|
||||
{
|
||||
ASSIGN(flattenedProperties, [coder decodeObjectForKey: @"flattenedProperties"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"objectRecords"])
|
||||
{
|
||||
ASSIGN(objectRecords, [coder decodeObjectForKey: @"objectRecords"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"connectionRecords"])
|
||||
{
|
||||
ASSIGN(connectionRecords, [coder decodeObjectForKey: @"connectionRecords"]);
|
||||
}
|
||||
// We could load more data here, but we currently don't need it.
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(connectionRecords);
|
||||
DESTROY(objectRecords);
|
||||
DESTROY(flattenedProperties);
|
||||
DESTROY(unlocalizedProperties);
|
||||
DESTROY(activeLocalization);
|
||||
DESTROY(localizations);
|
||||
DESTROY(sourceID);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString*) description
|
||||
{
|
||||
return [NSString stringWithFormat:
|
||||
@"%@ - sourceID: %@: maxID: %@: objectRecords: %@: flattenedProperties: %@: connectionRecords: %@: ",
|
||||
[super description], sourceID, maxID, objectRecords,
|
||||
flattenedProperties, connectionRecords];
|
||||
}
|
||||
|
||||
- (NSEnumerator*) connectionRecordEnumerator
|
||||
{
|
||||
return [connectionRecords objectEnumerator];
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectRecordEnumerator
|
||||
{
|
||||
return [[objectRecords orderedObjects] objectEnumerator];
|
||||
}
|
||||
|
||||
- (NSDictionary*) propertiesForObjectID: (id)objectID
|
||||
{
|
||||
NSEnumerator *en;
|
||||
NSString *idString;
|
||||
NSString *key;
|
||||
NSMutableDictionary *properties;
|
||||
int idLength;
|
||||
|
||||
idString = [NSString stringWithFormat: @"%@.", objectID];
|
||||
idLength = [idString length];
|
||||
properties = [[NSMutableDictionary alloc] init];
|
||||
en = [flattenedProperties keyEnumerator];
|
||||
while ((key = [en nextObject]) != nil)
|
||||
{
|
||||
if ([key hasPrefix: idString])
|
||||
{
|
||||
id value = [flattenedProperties objectForKey: key];
|
||||
[properties setObject: value forKey: [key substringFromIndex: idLength]];
|
||||
}
|
||||
}
|
||||
|
||||
return AUTORELEASE(properties);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a dictionary of the custom class names keyed on the objectIDs.
|
||||
*/
|
||||
- (NSDictionary*) customClassNames
|
||||
{
|
||||
NSMutableDictionary *properties;
|
||||
int i;
|
||||
|
||||
properties = [[NSMutableDictionary alloc] init];
|
||||
// We have special objects at -3, -2, -1 and 0
|
||||
for (i = -3; i < maxID; i++)
|
||||
{
|
||||
NSString *idString;
|
||||
id value;
|
||||
|
||||
idString = [NSString stringWithFormat: @"%d.CustomClassName", i];
|
||||
value = [flattenedProperties objectForKey: idString];
|
||||
if (value)
|
||||
{
|
||||
NSString *key;
|
||||
|
||||
key = [NSString stringWithFormat: @"%d", i];
|
||||
[properties setObject: value forKey: key];
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
- (id) nibInstantiate
|
||||
{
|
||||
NSEnumerator *en;
|
||||
id obj;
|
||||
|
||||
// iterate over connections, instantiate, and then establish them.
|
||||
en = [connectionRecords objectEnumerator];
|
||||
while ((obj = [en nextObject]) != nil)
|
||||
{
|
||||
[obj nibInstantiate];
|
||||
[obj establishConnection];
|
||||
}
|
||||
|
||||
// awaken all objects.
|
||||
en = [[objectRecords orderedObjects] objectEnumerator];
|
||||
while ((obj = [en nextObject]) != nil)
|
||||
{
|
||||
id realObj;
|
||||
NSDictionary *properties;
|
||||
id value;
|
||||
|
||||
realObj = [obj object];
|
||||
if ([realObj respondsToSelector: @selector(nibInstantiate)])
|
||||
{
|
||||
realObj = [realObj nibInstantiate];
|
||||
}
|
||||
|
||||
properties = [self propertiesForObjectID: [obj objectID]];
|
||||
NSDebugLLog(@"XIB", @"object %@ props %@", [obj objectID], properties);
|
||||
|
||||
//value = [properties objectForKey: @"windowTemplate.maxSize"];
|
||||
//value = [properties objectForKey: @"CustomClassName"];
|
||||
|
||||
// Activate windows
|
||||
value = [properties objectForKey: @"NSWindowTemplate.visibleAtLaunch"];
|
||||
if (value != nil)
|
||||
{
|
||||
if ([value boolValue] == YES)
|
||||
{
|
||||
if ([realObj isKindOfClass: [NSWindow class]])
|
||||
{
|
||||
// bring visible windows to front...
|
||||
[(NSWindow *)realObj orderFront: self];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tool tips
|
||||
value = [properties objectForKey: @"IBAttributePlaceholdersKey"];
|
||||
if (value != nil)
|
||||
{
|
||||
NSDictionary *infodict = (NSDictionary*)value;
|
||||
|
||||
// Process tooltips...
|
||||
IBToolTipAttribute *tooltip = [infodict objectForKey: @"ToolTip"];
|
||||
|
||||
if (tooltip && [realObj respondsToSelector: @selector(setToolTip:)])
|
||||
{
|
||||
[realObj setToolTip: [tooltip toolTip]];
|
||||
}
|
||||
|
||||
// Process XIB runtime attributes...
|
||||
if ([infodict objectForKey:@"IBUserDefinedRuntimeAttributesPlaceholderName"])
|
||||
{
|
||||
IBUserDefinedRuntimeAttributesPlaceholder *placeholder =
|
||||
[infodict objectForKey:@"IBUserDefinedRuntimeAttributesPlaceholderName"];
|
||||
NSArray *attributes = [placeholder runtimeAttributes];
|
||||
NSEnumerator *objectIter = [attributes objectEnumerator];
|
||||
IBUserDefinedRuntimeAttribute *attribute;
|
||||
|
||||
while ((attribute = [objectIter nextObject]) != nil)
|
||||
{
|
||||
[realObj setValue: [attribute value] forKeyPath: [attribute keyPath]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ([realObj respondsToSelector: @selector(awakeFromNib)])
|
||||
{
|
||||
[realObj awakeFromNib];
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface GSXibLoader: GSModelLoader
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,6 +1,42 @@
|
|||
/* <title>GSXibLoading</title>
|
||||
|
||||
<abstract>Xib (Cocoa XML) loading helper classes</abstract>
|
||||
|
||||
Copyright (C) 2010, 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Fred Kiefer <FredKiefer@gmx.de>
|
||||
Created: March 2010
|
||||
|
||||
Author: Gregory John Casamento
|
||||
Date: 2010, 2012
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
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 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.
|
||||
|
||||
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 02110 USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDebug.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSException.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSKeyedArchiver.h>
|
||||
#import "GNUstepGUI/GSXibElement.h"
|
||||
#import "AppKit/NSControl.h"
|
||||
#import "AppKit/NSNibLoading.h"
|
||||
#import "AppKit/NSWindow.h"
|
||||
#import "GNUstepGUI/GSNibLoading.h"
|
||||
#import "GNUstepGUI/GSXibLoading.h"
|
||||
|
||||
@interface IBAccessibilityAttribute : NSObject <NSCoding>
|
||||
|
@ -158,3 +194,831 @@
|
|||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation FirstResponder
|
||||
|
||||
+ (id) allocWithZone: (NSZone*)zone
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBClassDescriptionSource
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"majorKey"])
|
||||
{
|
||||
ASSIGN(majorKey, [coder decodeObjectForKey: @"majorKey"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"minorKey"])
|
||||
{
|
||||
ASSIGN(minorKey, [coder decodeObjectForKey: @"minorKey"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(majorKey);
|
||||
DESTROY(minorKey);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBPartialClassDescription
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"className"])
|
||||
{
|
||||
ASSIGN(className, [coder decodeObjectForKey: @"className"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"superclassName"])
|
||||
{
|
||||
ASSIGN(superclassName, [coder decodeObjectForKey: @"superclassName"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"actions"])
|
||||
{
|
||||
ASSIGN(actions, [coder decodeObjectForKey: @"actions"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"outlets"])
|
||||
{
|
||||
ASSIGN(outlets, [coder decodeObjectForKey: @"outlets"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"sourceIdentifier"])
|
||||
{
|
||||
ASSIGN(sourceIdentifier, [coder decodeObjectForKey: @"sourceIdentifier"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(className);
|
||||
DESTROY(superclassName);
|
||||
DESTROY(actions);
|
||||
DESTROY(outlets);
|
||||
DESTROY(sourceIdentifier);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBClassDescriber
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"referencedPartialClassDescriptions"])
|
||||
{
|
||||
ASSIGN(referencedPartialClassDescriptions, [coder decodeObjectForKey: @"referencedPartialClassDescriptions"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(referencedPartialClassDescriptions);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBConnection
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"label"])
|
||||
{
|
||||
ASSIGN(label, [coder decodeObjectForKey: @"label"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"source"])
|
||||
{
|
||||
ASSIGN(source, [coder decodeObjectForKey: @"source"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"destination"])
|
||||
{
|
||||
ASSIGN(destination, [coder decodeObjectForKey: @"destination"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(label);
|
||||
DESTROY(source);
|
||||
DESTROY(destination);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString*) label
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
- (id) source
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
- (id) destination
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
|
||||
- (NSNibConnector*) nibConnector
|
||||
{
|
||||
NSString *tag = [self label];
|
||||
NSRange colonRange = [tag rangeOfString: @":"];
|
||||
NSUInteger location = colonRange.location;
|
||||
NSNibConnector *result = nil;
|
||||
|
||||
if (location == NSNotFound)
|
||||
{
|
||||
result = [[NSNibOutletConnector alloc] init];
|
||||
}
|
||||
else
|
||||
{
|
||||
result = [[NSNibControlConnector alloc] init];
|
||||
}
|
||||
|
||||
[result setDestination: [self destination]];
|
||||
[result setSource: [self source]];
|
||||
[result setLabel: [self label]];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString*) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@ - label: %@, source: %@, destination: %@",
|
||||
[super description], label, NSStringFromClass([source class]),
|
||||
NSStringFromClass([destination class])];
|
||||
}
|
||||
|
||||
- (id) nibInstantiate
|
||||
{
|
||||
if ([source respondsToSelector: @selector(nibInstantiate)])
|
||||
{
|
||||
ASSIGN(source, [source nibInstantiate]);
|
||||
}
|
||||
if ([destination respondsToSelector: @selector(nibInstantiate)])
|
||||
{
|
||||
ASSIGN(destination, [destination nibInstantiate]);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBActionConnection
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
SEL sel = NSSelectorFromString(label);
|
||||
|
||||
[destination setTarget: source];
|
||||
[destination setAction: sel];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBOutletConnection
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
NS_DURING
|
||||
{
|
||||
if (source != nil)
|
||||
{
|
||||
NSString *selName;
|
||||
SEL sel;
|
||||
|
||||
selName = [NSString stringWithFormat: @"set%@%@:",
|
||||
[[label substringToIndex: 1] uppercaseString],
|
||||
[label substringFromIndex: 1]];
|
||||
sel = NSSelectorFromString(selName);
|
||||
|
||||
if (sel && [source respondsToSelector: sel])
|
||||
{
|
||||
[source performSelector: sel withObject: destination];
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We cannot use the KVC mechanism here, as this would always retain _dst
|
||||
* and it could also affect _setXXX methods and _XXX ivars that aren't
|
||||
* affected by the Cocoa code.
|
||||
*/
|
||||
const char *name = [label cString];
|
||||
Class class = object_getClass(source);
|
||||
Ivar ivar = class_getInstanceVariable(class, name);
|
||||
|
||||
if (ivar != 0)
|
||||
{
|
||||
object_setIvar(source, ivar, destination);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSWarnMLog(@"class '%@' has no instance var named: %@", NSStringFromClass(class), label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSLog(@"Error while establishing connection %@: %@",self,[localException reason]);
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBBindingConnection
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(connector);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
if (self == nil)
|
||||
return nil;
|
||||
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"connector"])
|
||||
{
|
||||
ASSIGN(connector, [coder decodeObjectForKey: @"connector"]);
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
[connector establishConnection];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBConnectionRecord
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"connection"])
|
||||
{
|
||||
ASSIGN(connection, [coder decodeObjectForKey: @"connection"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *format = [NSString stringWithFormat:@"%s:Can't decode %@ without a connection ID",
|
||||
__PRETTY_FUNCTION__,
|
||||
NSStringFromClass([self class])];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@", format];
|
||||
}
|
||||
|
||||
// Load the connection ID....
|
||||
if ([coder containsValueForKey: @"connectionID"])
|
||||
{
|
||||
// PRE-4.6 XIBs....
|
||||
connectionID = [coder decodeIntForKey: @"connectionID"];
|
||||
}
|
||||
else if ([coder containsValueForKey: @"id"])
|
||||
{
|
||||
// 4.6+ XIBs....
|
||||
NSString *string = [coder decodeObjectForKey: @"id"];
|
||||
|
||||
if (string && [string isKindOfClass:[NSString class]] && [string length])
|
||||
{
|
||||
connectionID = [string intValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *format = [NSString stringWithFormat:@"%s:class: %@ - connection ID is missing or zero!",
|
||||
__PRETTY_FUNCTION__, NSStringFromClass([self class])];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@", format];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *format = [NSString stringWithFormat:@"%s:Can't decode %@ without a connection ID",
|
||||
__PRETTY_FUNCTION__,
|
||||
NSStringFromClass([self class])];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@", format];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(connection);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (IBConnection*) connection
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
- (id) nibInstantiate
|
||||
{
|
||||
ASSIGN(connection, [connection nibInstantiate]);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) establishConnection
|
||||
{
|
||||
[connection establishConnection];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBToolTipAttribute
|
||||
|
||||
- (NSString*) toolTip
|
||||
{
|
||||
return toolTip;
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"name"])
|
||||
{
|
||||
ASSIGN(name, [coder decodeObjectForKey: @"name"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"object"])
|
||||
{
|
||||
ASSIGN(object, [coder decodeObjectForKey: @"object"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"toolTip"])
|
||||
{
|
||||
ASSIGN(toolTip, [coder decodeObjectForKey: @"toolTip"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(name);
|
||||
DESTROY(object);
|
||||
DESTROY(toolTip);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBInitialTabViewItemAttribute
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"name"])
|
||||
{
|
||||
ASSIGN(name, [coder decodeObjectForKey: @"name"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"object"])
|
||||
{
|
||||
ASSIGN(object, [coder decodeObjectForKey: @"object"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"initialTabViewItem"])
|
||||
{
|
||||
ASSIGN(initialTabViewItem, [coder decodeObjectForKey: @"initialTabViewItem"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(name);
|
||||
DESTROY(object);
|
||||
DESTROY(initialTabViewItem);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBObjectRecord
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"objectID"])
|
||||
{
|
||||
// PRE-4.6 XIBs....
|
||||
objectID = [coder decodeObjectForKey: @"objectID"];
|
||||
}
|
||||
else if ([coder containsValueForKey: @"id"])
|
||||
{
|
||||
// 4.6+ XIBs....
|
||||
objectID = [coder decodeObjectForKey: @"id"];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cannot process without object ID...
|
||||
NSString *format = [NSString stringWithFormat:@"%s:Can't decode %@ without an object ID",
|
||||
__PRETTY_FUNCTION__,
|
||||
NSStringFromClass([self class])];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"%@", format];
|
||||
}
|
||||
|
||||
if ([coder containsValueForKey: @"object"])
|
||||
{
|
||||
ASSIGN(object, [coder decodeObjectForKey: @"object"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"children"])
|
||||
{
|
||||
ASSIGN(children, [coder decodeObjectForKey: @"children"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"parent"])
|
||||
{
|
||||
ASSIGN(parent, [coder decodeObjectForKey: @"parent"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(object);
|
||||
DESTROY(children);
|
||||
DESTROY(parent);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) object
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
- (id) parent
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
- (id) objectID
|
||||
{
|
||||
return objectID;
|
||||
}
|
||||
|
||||
- (NSString *) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"<%@, %@, %@, %p>",
|
||||
[self className],
|
||||
object,
|
||||
parent,
|
||||
objectID];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBMutableOrderedSet
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"orderedObjects"])
|
||||
{
|
||||
ASSIGN(orderedObjects, [coder decodeObjectForKey: @"orderedObjects"]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(orderedObjects);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSArray*) orderedObjects
|
||||
{
|
||||
return orderedObjects;
|
||||
}
|
||||
|
||||
- (id) objectWithObjectID: (id)objID
|
||||
{
|
||||
NSEnumerator *en;
|
||||
IBObjectRecord *obj;
|
||||
|
||||
en = [orderedObjects objectEnumerator];
|
||||
while ((obj = [en nextObject]) != nil)
|
||||
{
|
||||
if ([[obj objectID] isEqual:objID])
|
||||
{
|
||||
return [obj object];
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IBObjectContainer
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)coder
|
||||
{
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
if ([coder containsValueForKey: @"sourceID"])
|
||||
{
|
||||
ASSIGN(sourceID, [coder decodeObjectForKey: @"sourceID"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"maxID"])
|
||||
{
|
||||
maxID = [coder decodeIntForKey: @"maxID"];
|
||||
}
|
||||
if ([coder containsValueForKey: @"flattenedProperties"])
|
||||
{
|
||||
ASSIGN(flattenedProperties, [coder decodeObjectForKey: @"flattenedProperties"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"objectRecords"])
|
||||
{
|
||||
ASSIGN(objectRecords, [coder decodeObjectForKey: @"objectRecords"]);
|
||||
}
|
||||
if ([coder containsValueForKey: @"connectionRecords"])
|
||||
{
|
||||
ASSIGN(connectionRecords, [coder decodeObjectForKey: @"connectionRecords"]);
|
||||
}
|
||||
// We could load more data here, but we currently don't need it.
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Can't decode %@ with %@.",NSStringFromClass([self class]),
|
||||
NSStringFromClass([coder class])];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(connectionRecords);
|
||||
DESTROY(objectRecords);
|
||||
DESTROY(flattenedProperties);
|
||||
DESTROY(unlocalizedProperties);
|
||||
DESTROY(activeLocalization);
|
||||
DESTROY(localizations);
|
||||
DESTROY(sourceID);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString*) description
|
||||
{
|
||||
return [NSString stringWithFormat:
|
||||
@"%@ - sourceID: %@: maxID: %@: objectRecords: %@: flattenedProperties: %@: connectionRecords: %@: ",
|
||||
[super description], sourceID, maxID, objectRecords,
|
||||
flattenedProperties, connectionRecords];
|
||||
}
|
||||
|
||||
- (NSEnumerator*) connectionRecordEnumerator
|
||||
{
|
||||
return [connectionRecords objectEnumerator];
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectRecordEnumerator
|
||||
{
|
||||
return [[objectRecords orderedObjects] objectEnumerator];
|
||||
}
|
||||
|
||||
- (NSDictionary*) propertiesForObjectID: (id)objectID
|
||||
{
|
||||
NSEnumerator *en;
|
||||
NSString *idString;
|
||||
NSString *key;
|
||||
NSMutableDictionary *properties;
|
||||
int idLength;
|
||||
|
||||
idString = [NSString stringWithFormat: @"%@.", objectID];
|
||||
idLength = [idString length];
|
||||
properties = [[NSMutableDictionary alloc] init];
|
||||
en = [flattenedProperties keyEnumerator];
|
||||
while ((key = [en nextObject]) != nil)
|
||||
{
|
||||
if ([key hasPrefix: idString])
|
||||
{
|
||||
id value = [flattenedProperties objectForKey: key];
|
||||
[properties setObject: value forKey: [key substringFromIndex: idLength]];
|
||||
}
|
||||
}
|
||||
|
||||
return AUTORELEASE(properties);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a dictionary of the custom class names keyed on the objectIDs.
|
||||
*/
|
||||
- (NSDictionary*) customClassNames
|
||||
{
|
||||
NSMutableDictionary *properties;
|
||||
int i;
|
||||
|
||||
properties = [[NSMutableDictionary alloc] init];
|
||||
// We have special objects at -3, -2, -1 and 0
|
||||
for (i = -3; i < maxID; i++)
|
||||
{
|
||||
NSString *idString;
|
||||
id value;
|
||||
|
||||
idString = [NSString stringWithFormat: @"%d.CustomClassName", i];
|
||||
value = [flattenedProperties objectForKey: idString];
|
||||
if (value)
|
||||
{
|
||||
NSString *key;
|
||||
|
||||
key = [NSString stringWithFormat: @"%d", i];
|
||||
[properties setObject: value forKey: key];
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
- (id) nibInstantiate
|
||||
{
|
||||
NSEnumerator *en;
|
||||
id obj;
|
||||
|
||||
// iterate over connections, instantiate, and then establish them.
|
||||
en = [connectionRecords objectEnumerator];
|
||||
while ((obj = [en nextObject]) != nil)
|
||||
{
|
||||
[obj nibInstantiate];
|
||||
[obj establishConnection];
|
||||
}
|
||||
|
||||
// awaken all objects.
|
||||
en = [[objectRecords orderedObjects] objectEnumerator];
|
||||
while ((obj = [en nextObject]) != nil)
|
||||
{
|
||||
id realObj;
|
||||
NSDictionary *properties;
|
||||
id value;
|
||||
|
||||
realObj = [obj object];
|
||||
if ([realObj respondsToSelector: @selector(nibInstantiate)])
|
||||
{
|
||||
realObj = [realObj nibInstantiate];
|
||||
}
|
||||
|
||||
properties = [self propertiesForObjectID: [obj objectID]];
|
||||
NSDebugLLog(@"XIB", @"object %@ props %@", [obj objectID], properties);
|
||||
|
||||
//value = [properties objectForKey: @"windowTemplate.maxSize"];
|
||||
//value = [properties objectForKey: @"CustomClassName"];
|
||||
|
||||
// Activate windows
|
||||
value = [properties objectForKey: @"NSWindowTemplate.visibleAtLaunch"];
|
||||
if (value != nil)
|
||||
{
|
||||
if ([value boolValue] == YES)
|
||||
{
|
||||
if ([realObj isKindOfClass: [NSWindow class]])
|
||||
{
|
||||
// bring visible windows to front...
|
||||
[(NSWindow *)realObj orderFront: self];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tool tips
|
||||
value = [properties objectForKey: @"IBAttributePlaceholdersKey"];
|
||||
if (value != nil)
|
||||
{
|
||||
NSDictionary *infodict = (NSDictionary*)value;
|
||||
|
||||
// Process tooltips...
|
||||
IBToolTipAttribute *tooltip = [infodict objectForKey: @"ToolTip"];
|
||||
|
||||
if (tooltip && [realObj respondsToSelector: @selector(setToolTip:)])
|
||||
{
|
||||
[realObj setToolTip: [tooltip toolTip]];
|
||||
}
|
||||
|
||||
// Process XIB runtime attributes...
|
||||
if ([infodict objectForKey:@"IBUserDefinedRuntimeAttributesPlaceholderName"])
|
||||
{
|
||||
IBUserDefinedRuntimeAttributesPlaceholder *placeholder =
|
||||
[infodict objectForKey:@"IBUserDefinedRuntimeAttributesPlaceholderName"];
|
||||
NSArray *attributes = [placeholder runtimeAttributes];
|
||||
NSEnumerator *objectIter = [attributes objectEnumerator];
|
||||
IBUserDefinedRuntimeAttribute *attribute;
|
||||
|
||||
while ((attribute = [objectIter nextObject]) != nil)
|
||||
{
|
||||
[realObj setValue: [attribute value] forKeyPath: [attribute keyPath]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ([realObj respondsToSelector: @selector(awakeFromNib)])
|
||||
{
|
||||
[realObj awakeFromNib];
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in a new issue