mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-22 18:11:06 +00:00
Merge pull request #147 from gnustep/custom_class_xib3_changes
This commit is contained in:
commit
fa1369cb64
5 changed files with 126 additions and 34 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
|||
2022-03-29 Gregory John Casamento <greg.casamento@gmail.com>
|
||||
|
||||
* Headers/Additions/GNUstepGUI/GSXibKeyedUnarchiver.h
|
||||
* Source/GSXib5KeyedUnarchiver.h
|
||||
* Source/GSXib5KeyedUnarchiver.m
|
||||
* Source/GSXibKeyedUnarchiver.m: Change format of
|
||||
customClass dictionary.
|
||||
|
||||
2022-03-26 Gregory John Casamento <greg.casamento@gmail.com>
|
||||
|
||||
* Headers/Additions/GNUstepGUI/GSXibKeyedUnarchiver.h: Add
|
||||
customClasses method and _customClasses ivar.
|
||||
* Source/GSXib5KeyedUnarchiver.h: Remove _customClasses from
|
||||
declarations here and the method as well.
|
||||
* Source/GSXib5KeyedUnarchiver.m: Remove customClasses method
|
||||
from here.
|
||||
* Source/GSXibKeyedUnarchiver.m: Implement logic here to build
|
||||
_customClasses array when loading a XIB of version 3 or 4.
|
||||
|
||||
2022-03-22 Riccardo Mottola <rm@gnu.org>
|
||||
|
||||
* Source/NSImageCell.m: subclass initImageCell, so that
|
||||
|
|
|
@ -41,18 +41,31 @@
|
|||
NSMutableArray *stack;
|
||||
GSXibElement *currentElement;
|
||||
NSMutableDictionary *decoded;
|
||||
NSMutableDictionary *_customClasses;
|
||||
}
|
||||
|
||||
+ (BOOL) checkXib5: (NSData *)data;
|
||||
|
||||
+ (NSKeyedUnarchiver *) unarchiverForReadingWithData: (NSData *)data;
|
||||
|
||||
- (void) _initCommon;
|
||||
|
||||
- (id) decodeObjectForXib: (GSXibElement*)element
|
||||
forClassName: (NSString*)classname
|
||||
withID: (NSString*)objID;
|
||||
|
||||
- (id) _decodeArrayOfObjectsForElement: (GSXibElement*)element;
|
||||
|
||||
- (id) _decodeDictionaryOfObjectsForElement: (GSXibElement*)element;
|
||||
|
||||
- (id) objectForXib: (GSXibElement*)element;
|
||||
|
||||
- (void) createCustomClassRecordForId: (NSString *)theId
|
||||
withParentClass: (NSString *)parentClassName
|
||||
forCustomClass: (NSString *)customClassName;
|
||||
|
||||
- (NSDictionary *) customClasses;
|
||||
|
||||
- (NSDictionary *) decoded;
|
||||
|
||||
@end
|
||||
|
|
|
@ -41,9 +41,7 @@
|
|||
GSXibElement *_runtimeAttributes;
|
||||
NSMutableDictionary *_orderedObjectsDict;
|
||||
NSArray *_resources;
|
||||
NSMutableArray *_customClasses;
|
||||
}
|
||||
|
||||
- (NSRange) decodeRangeForKey: (NSString*)key;
|
||||
- (NSMutableArray *) customClasses;
|
||||
@end
|
||||
|
|
|
@ -750,9 +750,6 @@ static NSArray *XmlBoolDefaultYes = nil;
|
|||
[_IBObjectContainer setElement: _connectionRecords forKey: @"connectionRecords"];
|
||||
[_IBObjectContainer setElement: _objectRecords forKey: @"objectRecords"];
|
||||
[_IBObjectContainer setElement: _flattenedProperties forKey: @"flattenedProperties"];
|
||||
|
||||
// Hold the dictionary which contains custom class information for Gorm/IB.
|
||||
_customClasses = [[NSMutableArray alloc] initWithCapacity: 10];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
|
@ -765,30 +762,9 @@ static NSArray *XmlBoolDefaultYes = nil;
|
|||
RELEASE(_orderedObjects);
|
||||
RELEASE(_orderedObjectsDict);
|
||||
RELEASE(_resources);
|
||||
RELEASE(_customClasses);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSMutableArray *) customClasses
|
||||
{
|
||||
return _customClasses;
|
||||
}
|
||||
|
||||
- (void) createCustomClassRecordForId: (NSString *)theId
|
||||
withParentClass: (NSString *)parentClassName
|
||||
forCustomClass: (NSString *)customClassName
|
||||
{
|
||||
if (theId == nil || customClassName == nil)
|
||||
return;
|
||||
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
theId, @"id",
|
||||
parentClassName, @"parentClassName",
|
||||
customClassName, @"customClassName",nil];
|
||||
[_customClasses addObject: dict];
|
||||
// NSLog(@"theId = %@, parentClassName = %@, customClassName = %@", theId, parentClassName, customClassName);
|
||||
}
|
||||
|
||||
- (void) parser: (NSXMLParser*)parser
|
||||
didStartElement: (NSString*)elementName
|
||||
namespaceURI: (NSString*)namespaceURI
|
||||
|
|
|
@ -83,6 +83,19 @@
|
|||
return AUTORELEASE(unarchiver);
|
||||
}
|
||||
|
||||
- (NSString *) _substituteClassForClassName: (NSString *)className
|
||||
{
|
||||
NSString *result = className;
|
||||
NSDictionary *dict = [_customClasses objectForKey: className];
|
||||
|
||||
if (dict != nil)
|
||||
{
|
||||
result = [dict objectForKey: @"parentClassName"];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSData *) _preProcessXib: (NSData *)data
|
||||
{
|
||||
NSData *result = data;
|
||||
|
@ -143,8 +156,47 @@
|
|||
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];
|
||||
NSString *cn = [[xmlObjs objectAtIndex: index] stringValue]; // className
|
||||
|
||||
[customClassDict setObject:cn forKey:key];
|
||||
|
||||
//
|
||||
// If we are in IB/Gorm build the custom classes map so that we don't instantiate
|
||||
// classes which don't exist (yet) in IB/Gorm. This allows editing of the model
|
||||
// in IB/Gorm. If we are in the live app, don't bother as it's a waste of memory.
|
||||
//
|
||||
if ([NSClassSwapper isInInterfaceBuilder] == YES)
|
||||
{
|
||||
NSUInteger idx = [key rangeOfString: @"."].location;
|
||||
if (idx != NSNotFound) // unlikely to be NSNotFound...
|
||||
{
|
||||
NSString *xpath = [NSString stringWithFormat: @"//object[@class=\"IBClassDescriber\"]"
|
||||
@"//string[@key=\"className\"][text()=\"%@\"]"
|
||||
@"/../string[@key=\"superclassName\"]", cn];
|
||||
NSArray *descriptionObjs = [document nodesForXPath: xpath error: NULL];
|
||||
if ([descriptionObjs count] > 0)
|
||||
{
|
||||
NSString *num = [key substringToIndex: idx];
|
||||
NSXMLNode *descriptionNode = [descriptionObjs objectAtIndex: 0];
|
||||
NSString *sc = [descriptionNode stringValue]; // superclassName
|
||||
NSString *refXPath = [NSString stringWithFormat:
|
||||
@"//object[@class=\"IBMutableOrderedSet\"][@key=\"objectRecords\"]"
|
||||
@"/object/object[@class=\"IBObjectRecord\"]/int[@key=\"objectID\"]"
|
||||
@"[text()=\"%@\"]/../reference[@key=\"object\"]/@ref", num];
|
||||
|
||||
NSArray *refNodes = [document nodesForXPath: refXPath error: NULL];
|
||||
if ([refNodes count] > 0)
|
||||
{
|
||||
NSXMLElement *refNode = [refNodes objectAtIndex: 0];
|
||||
NSString *refId = [refNode stringValue];
|
||||
|
||||
[self createCustomClassRecordForId: refId
|
||||
withParentClass: sc
|
||||
forCustomClass: cn];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,14 +258,16 @@
|
|||
|
||||
// If we are in the interface builder app, do not replace
|
||||
// the existing classes with their custom subclasses.
|
||||
if ([NSClassSwapper isInInterfaceBuilder] == NO)
|
||||
NSString *clsName = className;
|
||||
if ([NSClassSwapper isInInterfaceBuilder] == YES)
|
||||
{
|
||||
cls = NSClassFromString(className);
|
||||
clsName = [self _substituteClassForClassName: className];
|
||||
}
|
||||
|
||||
cls = NSClassFromString(clsName);
|
||||
classNode = [classNodes objectAtIndex:0];
|
||||
classAttr = [classNode attributeForName:@"class"];
|
||||
[classAttr setStringValue:className];
|
||||
[classAttr setStringValue: className];
|
||||
|
||||
if (cls != nil)
|
||||
{
|
||||
|
@ -232,7 +286,7 @@
|
|||
id cellAttr = nil;
|
||||
cellNode = [cellNodes objectAtIndex:0];
|
||||
cellAttr = [cellNode attributeForName:@"class"];
|
||||
[cellAttr setStringValue:cellClassString];
|
||||
[cellAttr setStringValue: cellClassString];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -264,6 +318,9 @@
|
|||
NSXMLParser *theParser;
|
||||
NSData *theData = data;
|
||||
|
||||
// Dictionary which contains custom class information for Gorm/IB.
|
||||
_customClasses = [[NSMutableDictionary alloc] init];
|
||||
|
||||
theData = [self _preProcessXib: data];
|
||||
if (theData == nil)
|
||||
{
|
||||
|
@ -298,6 +355,7 @@
|
|||
DESTROY(objects);
|
||||
DESTROY(stack);
|
||||
DESTROY(decoded);
|
||||
DESTROY(_customClasses);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
@ -364,11 +422,17 @@ didStartElement: (NSString*)elementName
|
|||
}
|
||||
}
|
||||
|
||||
- (id) allocObjectForClassName: (NSString*)classname
|
||||
- (id) allocObjectForClassName: (NSString*)clsname
|
||||
{
|
||||
Class c = nil;
|
||||
id delegate = [self delegate];
|
||||
|
||||
NSString *classname = clsname;
|
||||
|
||||
if ([NSClassSwapper isInInterfaceBuilder] == YES)
|
||||
{
|
||||
classname = [self _substituteClassForClassName: classname];
|
||||
}
|
||||
|
||||
c = [self classForClassName: classname];
|
||||
|
||||
if (c == nil)
|
||||
|
@ -1033,4 +1097,26 @@ didStartElement: (NSString*)elementName
|
|||
{
|
||||
return decoded;
|
||||
}
|
||||
|
||||
- (NSDictionary *) customClasses
|
||||
{
|
||||
return _customClasses;
|
||||
}
|
||||
|
||||
- (void) createCustomClassRecordForId: (NSString *)theId
|
||||
withParentClass: (NSString *)parentClassName
|
||||
forCustomClass: (NSString *)customClassName
|
||||
{
|
||||
if (theId == nil || customClassName == nil)
|
||||
return;
|
||||
|
||||
NSMutableDictionary *dict =
|
||||
[NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
parentClassName, @"parentClassName",
|
||||
theId, @"id",nil];
|
||||
|
||||
[_customClasses setObject: dict
|
||||
forKey: customClassName];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in a new issue