Initial code for XIB 5 support.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@37761 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Gregory John Casamento 2014-03-25 07:59:36 +00:00
parent 51c43eae39
commit 3931ffd3eb
9 changed files with 550 additions and 234 deletions

View file

@ -1,3 +1,17 @@
2014-03-25 03:56-EDT Gregory John Casamento <greg.casamento@gmail.com>
* Headers/Additions/GNUstepGUI/GSXibElement.h
* Headers/Additions/GNUstepGUI/GSXibLoading.h
* Headers/Additions/GNUstepGUI/GSXibObjectContainer.h
* Headers/Additions/GNUstepGUI/GSXibParser.h
* Source/GNUmakefile: Add new files to makefile.
* Source/GSXibElement.m: Refactored out of GSXibLoader.m
* Source/GSXibLoader.m: Remove some code and move into
separate files.
* Source/GSXibParser.m: Version 5 XIB support. Initial code. This
currently doesn't work, but it illustrates the direction I am
taking with solving this.
2014-02-23 Fred Kiefer <FredKiefer@gmx.de>
* Headers/AppKit/NSTextAttachment.h

View file

@ -0,0 +1,59 @@
/* <title>GSXibLoading</title>
<abstract>Xib (Cocoa XML) model loader</abstract>
Copyright (C) 2010 Free Software Foundation, Inc.
Written by: Fred Kiefer <FredKiefer@gmx.de>
Created: March 2010
Refactored slightly by: Gregory Casamento <greg.casamento@gmail.com>
Created: May 2010
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 Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#ifndef _GNUstep_H_GSXibElement
#define _GNUstep_H_GSXibElement
#import <Foundation/NSObject.h>
@class NSString, NSDictionary, NSMutableDictionary, NSMutableArray;
@interface GSXibElement: NSObject
{
NSString *type;
NSDictionary *attributes;
NSString *value;
NSMutableDictionary *elements;
NSMutableArray *values;
}
- (GSXibElement*) initWithType: (NSString*)typeName
andAttributes: (NSDictionary*)attribs;
- (NSString*) type;
- (NSString*) value;
- (NSDictionary*) elements;
- (NSArray*) values;
- (void) addElement: (GSXibElement*)element;
- (void) setElement: (GSXibElement*)element forKey: (NSString*)key;
- (void) setValue: (NSString*)text;
- (NSString*) attributeForKey: (NSString*)key;
- (GSXibElement*) elementForKey: (NSString*)key;
@end
#endif

View file

@ -34,6 +34,7 @@
@class NSString, NSDictionary, NSArray, NSMutableDictionary, NSMutableArray;
@class NSNibBindingConnector;
@class GSXibElement;
// Hack: This allows the class name FirstResponder in NSCustomObject and
// correctly returns nil as the corresponding object.
@ -155,25 +156,6 @@
- (NSEnumerator *) objectRecordEnumerator;
@end
@interface GSXibElement: NSObject
{
NSString *type;
NSDictionary *attributes;
NSString *value;
NSMutableDictionary *elements;
NSMutableArray *values;
}
- (NSString*) type;
- (NSString*) value;
- (NSDictionary*) elements;
- (NSArray*) values;
- (void) addElement: (GSXibElement*)element;
- (void) setElement: (GSXibElement*)element forKey: (NSString*)key;
- (void) setValue: (NSString*)text;
- (NSString*) attributeForKey: (NSString*)key;
- (GSXibElement*) elementForKey: (NSString*)key;
@end
@interface GSXibKeyedUnarchiver: NSKeyedUnarchiver
{
NSMutableDictionary *objects;

View file

@ -0,0 +1,30 @@
/* <title>GSXibObjectContainer</title>
<abstract>Xib v5 (Cocoa XML) container</abstract>
Copyright (C) 2014 Free Software Foundation, Inc.
Written by: Gregory Casamento <greg.casamento@gmail.com>
Created: March 2014
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 Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#import <Foundation/NSObject.h>
@interface GSXibObjectContainer : NSObject
@end

View file

@ -0,0 +1,51 @@
/* <title>GSXibParser</title>
<abstract>Xib v5 (Cocoa XML) parser</abstract>
Copyright (C) 2014 Free Software Foundation, Inc.
Written by: Gregory Casamento <greg.casamento@gmail.com>
Created: March 2014
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 Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#ifndef _GNUstep_H_GSXibParser
#define _GNUstep_H_GSXibParser
#import <Foundation/NSObject.h>
@class NSData;
@class NSXMLParser;
@class NSMutableDictionary;
@class GSXibElement;
@class NSMutableArray;
@interface GSXibParser : NSObject
{
NSMutableDictionary *objects;
GSXibElement *currentElement;
NSMutableArray *stack;
NSXMLParser *theParser;
}
- (id) initWithData: (NSData *)data;
- (NSDictionary *) parse;
@end
#endif

View file

@ -247,8 +247,10 @@ GSModelLoaderFactory.m \
GSGormLoader.m \
GSGModelLoader.m \
GSNibLoader.m \
GSXibElement.m \
GSXibLoader.m \
GSXibLoading.m \
GSXibParser.m \
GSHelpAttachment.m
# Turn off NSMenuItem warning that NSMenuItem conforms to <NSObject>,
@ -464,7 +466,9 @@ GSInstantiator.h \
GSSoundSink.h \
GSSoundSource.h \
GSWindowDecorationView.h \
GSXibElement.h \
GSXibLoading.h \
GSXibParser.h \
GSHelpAttachment.h
libgnustep-gui_HEADER_FILES = ${GUI_HEADERS}

111
Source/GSXibElement.m Normal file
View file

@ -0,0 +1,111 @@
/* <title>GSXibElement</title>
<abstract>Xib element</abstract>
Copyright (C) 2010, 2011 Free Software Foundation, Inc.
Written by: Fred Kiefer <FredKiefer@gmx.de>
Created: March 2010
Written by: Gregory Casamento <greg.casamento@gmail.com>
Created: March 2014
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 Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import "GNUstepGUI/GSXibElement.h"
@implementation GSXibElement
- (GSXibElement*) initWithType: (NSString*)typeName
andAttributes: (NSDictionary*)attribs
{
ASSIGN(type, typeName);
ASSIGN(attributes, attribs);
elements = [[NSMutableDictionary alloc] init];
values = [[NSMutableArray alloc] init];
return self;
}
- (void) dealloc
{
DESTROY(type);
DESTROY(attributes);
DESTROY(elements);
DESTROY(values);
DESTROY(value);
[super dealloc];
}
- (NSString*) type
{
return type;
}
- (NSString*) value
{
return value;
}
- (NSDictionary*) elements
{
return elements;
}
- (NSArray*) values
{
return values;
}
- (void) addElement: (GSXibElement*)element
{
[values addObject: element];
}
- (void) setElement: (GSXibElement*)element forKey: (NSString*)key
{
[elements setObject: element forKey: key];
}
- (void) setValue: (NSString*)text
{
ASSIGN(value, text);
}
- (NSString*) attributeForKey: (NSString*)key
{
return [attributes objectForKey: key];
}
- (GSXibElement*) elementForKey: (NSString*)key
{
return [elements objectForKey: key];
}
- (NSString*) description
{
return [NSString stringWithFormat:
@"GSXibElement <%@> attrs (%@) elements [%@] values [%@] %@",
type, attributes, elements, values, value, nil];
}
@end

View file

@ -45,6 +45,9 @@
#import "GNUstepGUI/GSModelLoaderFactory.h"
#import "GNUstepGUI/GSNibLoading.h"
#import "GNUstepGUI/GSXibLoading.h"
#import "GNUstepGUI/GSXibParser.h"
#import "GNUstepGUI/GSXibObjectContainer.h"
#import "GNUstepGUI/GSXibElement.h"
@interface NSApplication (NibCompatibility)
- (void) _setMainMenu: (NSMenu*)aMenu;
@ -853,7 +856,7 @@
}
- (void) awake: (NSArray *)rootObjects
inContainer: (IBObjectContainer *)objects
inContainer: (id)objects
withContext: (NSDictionary *)context
{
NSEnumerator *en;
@ -903,7 +906,10 @@
}
// Load connections and awaken objects
[objects nibInstantiate];
if ([objects respondsToSelector:@selector(nibInstantiate)])
{
[objects nibInstantiate];
}
}
- (BOOL) loadModelData: (NSData *)data
@ -928,13 +934,28 @@
rootObjects = [unarchiver decodeObjectForKey: @"IBDocument.RootObjects"];
objects = [unarchiver decodeObjectForKey: @"IBDocument.Objects"];
NSDebugLLog(@"XIB", @"rootObjects %@", rootObjects);
[self awake: rootObjects inContainer: objects withContext: context];
[self awake: rootObjects
inContainer: objects
withContext: context];
loaded = YES;
RELEASE(unarchiver);
}
else
{
NSLog(@"Could not instantiate Xib unarchiver.");
GSXibParser *parser = [[GSXibParser alloc] initWithData: data];
NSDictionary *result = [parser parse];
if (result != nil)
{
NSArray *rootObjects = [result objectForKey: @"IBDocument.RootObjects"];
GSXibObjectContainer *objects = [result objectForKey: @"IBDocument.Objects"];
[self awake: rootObjects
inContainer: objects
withContext: context];
}
else
{
NSLog(@"Could not instantiate Xib unarchiver/Unable to parse Xib.");
}
}
}
else
@ -983,83 +1004,6 @@
@end
@implementation GSXibElement
- (GSXibElement*) initWithType: (NSString*)typeName
andAttributes: (NSDictionary*)attribs
{
ASSIGN(type, typeName);
ASSIGN(attributes, attribs);
elements = [[NSMutableDictionary alloc] init];
values = [[NSMutableArray alloc] init];
return self;
}
- (void) dealloc
{
DESTROY(type);
DESTROY(attributes);
DESTROY(elements);
DESTROY(values);
DESTROY(value);
[super dealloc];
}
- (NSString*) type
{
return type;
}
- (NSString*) value
{
return value;
}
- (NSDictionary*) elements
{
return elements;
}
- (NSArray*) values
{
return values;
}
- (void) addElement: (GSXibElement*)element
{
[values addObject: element];
}
- (void) setElement: (GSXibElement*)element forKey: (NSString*)key
{
[elements setObject: element forKey: key];
}
- (void) setValue: (NSString*)text
{
ASSIGN(value, text);
}
- (NSString*) attributeForKey: (NSString*)key
{
return [attributes objectForKey: key];
}
- (GSXibElement*) elementForKey: (NSString*)key
{
return [elements objectForKey: key];
}
- (NSString*) description
{
return [NSString stringWithFormat:
@"GSXibElement <%@> attrs (%@) elements [%@] values [%@] %@",
type, attributes, elements, values, value, nil];
}
@end
@implementation GSXibKeyedUnarchiver
- (NSData *) _preProcessXib: (NSData *)data
@ -1074,143 +1018,154 @@
}
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)
// 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;
}
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]])
{
[customClassDict setObject:[node stringValue] forKey:key];
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];
}
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;
if (cls != nil)
refId = [[record attributeForName:@"ref"] stringValue];
refXpath = [NSString stringWithFormat:@"//object[@id=\"%@\"]",refId];
classNodes = [document nodesForXPath:refXpath
error:NULL];
if([classNodes count] > 0)
{
if ([cls respondsToSelector:@selector(cellClass)])
id classAttr = nil;
Class cls = NSClassFromString(className);
classNode = [classNodes objectAtIndex:0];
classAttr = [classNode attributeForName:@"class"];
[classAttr setStringValue:className];
if (cls != nil)
{
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)
if ([cls respondsToSelector:@selector(cellClass)])
{
NSString *cellClassString = NSStringFromClass(cellClass);
id cellAttr = nil;
cellNode = [cellNodes objectAtIndex:0];
cellAttr = [cellNode attributeForName:@"class"];
[cellAttr setStringValue:cellClassString];
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);
}
}
}
}
}
}
result = [document XMLData];
RELEASE(document);
}
}
return result;
@ -1223,11 +1178,16 @@
// If we are in the interface builder app, do not replace
// the existing classes with their custom subclasses.
if([NSClassSwapper isInInterfaceBuilder] == NO)
if ([NSClassSwapper isInInterfaceBuilder] == NO)
{
theData = [self _preProcessXib: data];
}
if (theData == nil)
{
return nil;
}
objects = [[NSMutableDictionary alloc] init];
stack = [[NSMutableArray alloc] init];
decoded = [[NSMutableDictionary alloc] init];
@ -1281,12 +1241,6 @@ didStartElement: (NSString*)elementName
// FIXME: We should use proper memory management here
AUTORELEASE(element);
if ([@"document" isEqualToString: elementName])
{
[NSException raise: NSInvalidArgumentException
format: @"Cannot decode XIB 5 format."];
}
if (key != nil)
{
[currentElement setElement: element forKey: key];

111
Source/GSXibParser.m Normal file
View file

@ -0,0 +1,111 @@
/* <title>GSXibParser</title>
<abstract>Xib v5 (Cocoa XML) parser</abstract>
Copyright (C) 2014 Free Software Foundation, Inc.
Written by: Gregory Casamento <greg.casamento@gmail.com>
Created: March 2014
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 Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSXMLParser.h>
#import <Foundation/NSString.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSException.h>
#import "GNUstepGUI/GSXibParser.h"
#import "GNUstepGUI/GSXibElement.h"
@implementation GSXibParser
- (id) initWithData: (NSData *)data
{
if ((self = [super init]) != nil)
{
theParser = [[NSXMLParser alloc] initWithData: data];
[theParser setDelegate: self];
objects = [[NSMutableDictionary alloc] initWithCapacity: 100];
stack = [[NSMutableArray alloc] initWithCapacity: 100];
currentElement = nil;
}
return self;
}
- (NSDictionary *) parse
{
NS_DURING
{
[theParser parse];
}
NS_HANDLER
{
NSLog(@"%@",[localException reason]);
}
NS_ENDHANDLER;
return objects;
}
- (void) parser: (NSXMLParser*)parser
foundCharacters: (NSString*)string
{
[currentElement setValue: string];
}
- (void) parser: (NSXMLParser*)parser
didStartElement: (NSString*)elementName
namespaceURI: (NSString*)namespaceURI
qualifiedName: (NSString*)qualifiedName
attributes: (NSDictionary*)attributeDict
{
GSXibElement *element = [[GSXibElement alloc] initWithType: elementName
andAttributes: attributeDict];
NSString *key = [attributeDict objectForKey: @"id"];
// FIXME: We should use proper memory management here
AUTORELEASE(element);
if (key != nil)
{
[currentElement setElement: element forKey: key];
}
else
{
// For Arrays
[currentElement addElement: element];
}
// Maintain the stack...
[stack addObject: currentElement];
currentElement = element;
}
- (void) parser: (NSXMLParser*)parser
didEndElement: (NSString*)elementName
namespaceURI: (NSString*)namespaceURI
qualifiedName: (NSString*)qName
{
currentElement = [stack lastObject];
[stack removeLastObject];
}
@end