More refactoring. Architectural improvments are coming.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/gorm/trunk@19373 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Gregory John Casamento 2004-05-19 01:36:37 +00:00
parent 045d4d78cd
commit d9c26fa4af
9 changed files with 767 additions and 685 deletions

View file

@ -1,3 +1,24 @@
2004-05-18 07:20 Gregory John Casamento <greg_casamento@yahoo.com>
* GModelDecoder.m: Changed reference to the class loader.
* Gorm.m: Added code to inactivate menu items when a
class isn't selected. Moved some code to decide what is
instantiable to the GormClassManager.
* GormDocument.m: Moved the parseHeader: method to
GormClassManager where it belongs. All methods dealing with
loading classes into Gorm or creating class files from data within
the application belong in GormClassManager. Changed references
to the call where appropriate in the code. Added document as
observer when a class is added. This is to help factilitate the
move of the parseHeader method. Moved the init method near the top
of the file.
* GormClassManager.m: added parseHeader method to process headers
into data usable by Gorm. Added an instance variable to cache the
document when a class manager is instantiated. The class manager
needs to communicate with the document it belongs to frequently.
* GormSoundInspector.m: Backed out previous change.
* GormSoundInspector.h: Removed _currentSound ivar.
2004-05-16 07:20 Gregory John Casamento <greg_casamento@yahoo.com>
* Gorm.m: in testInterface: bring the temporary menu to the

View file

@ -269,8 +269,10 @@ static BOOL gormFileOwnerDecoded;
NSLog(@"Failed to add class %@ with superclass of %@.", classname, superClass);
}
}
[self parseHeader: header];
else
{
[classManager parseHeader: header];
}
}
/* Replace the proxy with the real object if necessary and make sure there

99
Gorm.m
View file

@ -1336,6 +1336,26 @@ NSString *GormResizeCellNotification = @"GormResizeCellNotification";
return NO;
}
if(sel_eq(action, @selector(createSubclass:)))
{
NSArray *s = [selectionOwner selection];
id o = nil;
NSString *name = nil;
if([s count] == 0 || [s count] > 1)
return NO;
o = [s objectAtIndex: 0];
name = [o className];
if([active classIsSelected] == NO)
{
return NO;
}
if([name isEqual: @"FirstResponder"])
return NO;
}
if(sel_eq(action, @selector(addAttributeToClass:)) ||
sel_eq(action, @selector(createClassFiles:)) ||
@ -1360,7 +1380,11 @@ NSString *GormResizeCellNotification = @"GormResizeCellNotification";
{
return NO;
}
if([name isEqual: @"FirstResponder"])
return NO;
}
if(sel_eq(action, @selector(instantiateClass:)))
{
NSArray *s = [selectionOwner selection];
@ -1376,80 +1400,17 @@ NSString *GormResizeCellNotification = @"GormResizeCellNotification";
return NO;
}
if([active classIsSelected] == NO)
{
return NO;
}
o = [s objectAtIndex: 0];
name = [o className];
if(name != nil)
{
id cm = [self classManager];
// there are some classes which can't be instantiated directly
// in Gorm.
if([cm isSuperclass: @"NSApplication" linkedToClass: name] ||
[name isEqualToString: @"NSApplication"])
{
return NO;
}
if([cm isSuperclass: @"NSCell" linkedToClass: name] ||
[name isEqualToString: @"NSCell"])
{
return NO;
}
else if([name isEqualToString: @"NSDocument"])
{
return NO;
}
else if([name isEqualToString: @"NSDocumentController"])
{
return NO;
}
else if([name isEqualToString: @"NSFontManager"])
{
return NO;
}
else if([name isEqualToString: @"NSHelpManager"])
{
return NO;
}
else if([name isEqualToString: @"NSImage"])
{
return NO;
}
else if([cm isSuperclass: @"NSMenuItem" linkedToClass: name] ||
[name isEqualToString: @"NSMenuItem"])
{
return NO;
}
else if([name isEqualToString: @"NSResponder"])
{
return NO;
}
else if([cm isSuperclass: @"NSSound" linkedToClass: name] ||
[name isEqualToString: @"NSSound"])
{
return NO;
}
else if([cm isSuperclass: @"NSTableColumn" linkedToClass: name] ||
[name isEqualToString: @"NSTableColumn"])
{
return NO;
}
else if([cm isSuperclass: @"NSTableViewItem" linkedToClass: name] ||
[name isEqualToString: @"NSTableViewItem"])
{
return NO;
}
else if([cm isSuperclass: @"NSWindow" linkedToClass: name] ||
[name isEqualToString: @"NSWindow"])
{
return NO;
}
else if([cm isSuperclass: @"FirstResponder" linkedToClass: name] ||
[name isEqualToString: @"FirstResponder"])
{
// special case, FirstResponder.
return NO;
}
NSDebugLog(@"Selection is %@",name);
return [cm canInstantiateClassNamed: name];
}
}
}

View file

@ -11,7 +11,9 @@
NSMutableDictionary *classInformation;
NSMutableArray *customClasses;
NSMutableDictionary *customClassMap;
id document;
}
- (id) initWithDocument: (id)aDocument;
- (void) addAction: (NSString*)anAction forObject: (id)anObject;
- (void) addOutlet: (NSString*)anOutlet forObject: (id)anObject;
- (NSArray*) allActionsForClassNamed: (NSString*)className;
@ -53,7 +55,7 @@
- (BOOL) makeSourceAndHeaderFilesForClass: (NSString*)className
withName:(NSString*)sourcePath
and:(NSString*)headerPath;
- (BOOL) parseHeader: (NSString *)headerPath;
- (BOOL) saveToFile: (NSString*)path;
- (BOOL) loadFromFile: (NSString*)path;
- (BOOL) loadCustomClasses: (NSString*)path;
@ -62,6 +64,7 @@
- (BOOL) isAction: (NSString *)actionName ofClass: (NSString *)className;
- (BOOL) isOutlet: (NSString *)outletName ofClass: (NSString *)className;
- (NSArray *) allSuperClassesOf: (NSString *)className;
- (BOOL) canInstantiateClassNamed: (NSString *)className;
// custom class support...
- (NSString *) customClassForObject: (id)object;

View file

@ -37,11 +37,10 @@
- (void) _touch
{
id<IBDocuments> doc = [(id<IB>)NSApp activeDocument];
[[NSNotificationCenter defaultCenter]
postNotificationName: GormDidModifyClassNotification
object: self];
[doc touch];
[document touch];
}
- (NSString*) addClassWithSuperClassName: (NSString*)name
@ -802,7 +801,7 @@
return [info objectForKey: @"ExtraOutlets"];
}
- (id) init
- (id) initWithDocument: (id)aDocument
{
self = [super init];
if (self != nil)
@ -810,6 +809,8 @@
NSBundle *bundle = [NSBundle mainBundle];
NSString *path;
document = aDocument; // the document retains us, this is for convenience
path = [bundle pathForResource: @"ClassInformation" ofType: @"plist"];
if (path == nil)
{
@ -1344,6 +1345,273 @@
return YES;
}
- (BOOL) parseHeader: (NSString *)headerPath
{
NSString *headerFile = [NSString stringWithContentsOfFile: headerPath];
NSScanner *headerScanner = [NSScanner scannerWithString: headerFile];
NSCharacterSet *superClassStopSet = [NSCharacterSet characterSetWithCharactersInString: @" \n"];
NSCharacterSet *classStopSet = [NSCharacterSet characterSetWithCharactersInString: @" :"];
NSCharacterSet *categoryStopSet = [NSCharacterSet characterSetWithCharactersInString: @" ("];
NSCharacterSet *typeStopSet = [NSCharacterSet characterSetWithCharactersInString: @" "];
NSCharacterSet *actionStopSet = [NSCharacterSet characterSetWithCharactersInString: @";:"];
NSCharacterSet *outletStopSet = [NSCharacterSet characterSetWithCharactersInString: @";,"];
NSCharacterSet *illegalOutletSet = [NSCharacterSet characterSetWithCharactersInString: @"~`@#$%^&*()+={}|[]\\:;'<>?,./"];
NSCharacterSet *illegalActionSet = [NSCharacterSet characterSetWithCharactersInString: @"~`@#$%^&*()+={}|[]\\;'<>?,./"];
NSArray *outletTokens = [NSArray arrayWithObjects: @"id", @"IBOutlet", nil];
NSArray *actionTokens = [NSArray arrayWithObjects: @"(void)", @"(IBAction)", @"(id)", nil];
NSRange notFoundRange = NSMakeRange(NSNotFound,0);
// NSCharacterSet *commentStopSet = [NSCharacterSet characterSetWithCharactersInString: @"\n"];
while (![headerScanner isAtEnd])
{
NSString *classString = nil;
BOOL classfound = NO, result = NO, category = NO;
NSEnumerator *outletEnum = [outletTokens objectEnumerator];
NSEnumerator *actionEnum = [actionTokens objectEnumerator];
NSString *outletToken = nil;
NSString *actionToken = nil;
int alert;
classfound = [headerScanner scanUpToString: @"@interface"
intoString: NULL];
[headerScanner scanUpToString: @"@end"
intoString: &classString];
if (classfound && ![headerScanner isAtEnd])
{
NSString
*className = nil,
*superClassName = nil,
*ivarString = nil,
*methodString = nil;
NSScanner
*classScanner = [NSScanner scannerWithString: classString],
*ivarScanner = nil,
*methodScanner = nil;
NSMutableArray
*actions = [NSMutableArray array],
*outlets = [NSMutableArray array];
[classScanner scanString: @"@interface"
intoString: NULL];
[classScanner scanUpToCharactersFromSet: classStopSet
intoString: &className];
[classScanner scanString: @":"
intoString: NULL];
[classScanner scanUpToCharactersFromSet: superClassStopSet
intoString: &superClassName];
[classScanner scanUpToString: @"{"
intoString: NULL];
[classScanner scanUpToString: @"}"
intoString: &ivarString];
category = (ivarString == nil);
if(!category)
{
[classScanner scanUpToString: @"@end"
intoString: &methodString];
NSDebugLog(@"Found a class \"%@\" with super class \"%@\"", className,
superClassName);
}
else
{
NSDebugLog(@"A CATEGORY");
classScanner = [NSScanner scannerWithString: classString];
[classScanner scanString: @"@interface"
intoString: NULL];
[classScanner scanUpToCharactersFromSet: categoryStopSet
intoString: &className];
[classScanner scanString: @"("
intoString: NULL];
[classScanner scanUpToCharactersFromSet: superClassStopSet
intoString: &superClassName];
[classScanner scanString: @")"
intoString: NULL];
[classScanner scanUpToString: @"@end"
intoString: &methodString];
NSDebugLog(@"method String %@",methodString);
}
// if its' not a category and it's known, ask before proceeding...
if([self isKnownClass: className] && !category)
{
NSString *message = [NSString stringWithFormat:
_(@"The class %@ already exists. Replace it?"),
className];
alert = NSRunAlertPanel(_(@"Problem adding class from header"),
message,
_(@"Yes"),
_(@"No"),
nil);
if (alert != NSAlertDefaultReturn)
return NO;
}
// if it's not a category go through the ivars...
if(!category)
{
NSDebugLog(@"Ivar string is not nil");
// Interate over the possible tokens which can make an
// ivar an outlet.
while ((outletToken = [outletEnum nextObject]) != nil)
{
NSString *delimiter = nil;
NSDebugLog(@"outlet Token = %@", outletToken);
// Scan the variables of the class...
ivarScanner = [NSScanner scannerWithString: ivarString];
while (![ivarScanner isAtEnd])
{
NSString *outlet = nil;
NSString *type = nil;
if (delimiter == nil || [delimiter isEqualToString: @";"])
{
[ivarScanner scanUpToString: outletToken
intoString: NULL];
[ivarScanner scanString: outletToken
intoString: NULL];
}
// if using the IBOutlet token in the header, scan in the outlet type
// as well.
if([outletToken isEqualToString: @"IBOutlet"])
{
[ivarScanner scanUpToCharactersFromSet: typeStopSet
intoString: NULL];
[ivarScanner scanCharactersFromSet: typeStopSet
intoString: NULL];
[ivarScanner scanUpToCharactersFromSet: typeStopSet
intoString: &type];
NSDebugLog(@"outlet type = %@",type);
}
[ivarScanner scanUpToCharactersFromSet: outletStopSet
intoString: &outlet];
[ivarScanner scanCharactersFromSet: outletStopSet
intoString: &delimiter];
if ([ivarScanner isAtEnd] == NO
&& [outlets indexOfObject: outlet] == NSNotFound)
{
NSDebugLog(@"outlet = %@", outlet);
if(NSEqualRanges([outlet rangeOfCharacterFromSet: illegalOutletSet],notFoundRange))
{
[outlets addObject: outlet];
}
}
}
}
}
while ((actionToken = [actionEnum nextObject]) != nil)
{
NSDebugLog(@"Action token %@", actionToken);
methodScanner = [NSScanner scannerWithString: methodString];
while (![methodScanner isAtEnd])
{
NSString *action = nil;
BOOL hasArguments = NO;
// Scan the method name
[methodScanner scanUpToString: actionToken
intoString: NULL];
[methodScanner scanString: actionToken
intoString: NULL];
[methodScanner scanUpToCharactersFromSet: actionStopSet
intoString: &action];
// This will return true if the method has args.
hasArguments = [methodScanner scanString: @":"
intoString: NULL];
if (hasArguments)
{
BOOL isAction = NO;
NSString *argType = nil;
// If the argument is (id) then the method can
// be considered an action and we add it to the list.
isAction = [methodScanner scanString: @"(id)"
intoString: &argType];
if (![methodScanner isAtEnd])
{
if (isAction)
{
/* Add the ':' back */
action = [action stringByAppendingString: @":"];
NSDebugLog(@"action = %@", action);
if(NSEqualRanges([action rangeOfCharacterFromSet: illegalActionSet],notFoundRange))
{
[actions addObject: action];
}
}
else
{
NSDebugLog(@"Not an action");
}
}
}
} // end while
} // end while
if([self isKnownClass: className] &&
[self isCustomClass: className] && category)
{
[self addActions: actions forClassNamed: className];
[self addOutlets: outlets forClassNamed: className];
result = YES;
}
else if(!category)
{
result = [self addClassNamed: className
withSuperClassNamed: superClassName
withActions: actions
withOutlets: outlets];
}
if (result)
{
NSDebugLog(@"Class %@ added", className);
}
else
if (alert == NSAlertDefaultReturn)
{
[self removeClassNamed: className];
result = [self addClassNamed: className
withSuperClassNamed: superClassName
withActions: actions
withOutlets: outlets];
if (!result)
{
NSString *message = [NSString stringWithFormat:
_(@"Could not replace class %@."), className];
NSRunAlertPanel(_(@"Problem adding class from header"),
message,
nil,
nil,
nil);
NSDebugLog(@"Class %@ failed to add", className);
}
else
{
NSDebugLog(@"Class %@ replaced.", className);
}
}
if (result)
{
[[NSNotificationCenter defaultCenter]
postNotificationName: GormDidAddClassNotification
object: self];
[document selectClass: className];
}
} // if we found a class
}
return YES;
}
- (BOOL) isAction: (NSString *)name ofClass: (NSString *)className
{
BOOL result = NO;
@ -1391,7 +1659,7 @@
- (NSString *) customClassForObject: (id)object
{
NSString *name = [[(id<IB>)NSApp activeDocument] nameForObject: object];
NSString *name = [document nameForObject: object];
NSString *result = [self customClassForName: name];
// NSString *result = [customClassMap objectForKey: name];
NSDebugLog(@"in customClassForObject: object = %@, name = %@, result = %@, customClassMap = %@",
@ -1489,6 +1757,79 @@
}
}
// There are some classes which can't be instantiated directly
// in Gorm. These are they.. (GJC)
- (BOOL) canInstantiateClassNamed: (NSString *)className
{
if([self isSuperclass: @"NSApplication" linkedToClass: className] ||
[className isEqualToString: @"NSApplication"])
{
return NO;
}
else if([self isSuperclass: @"NSCell" linkedToClass: className] ||
[className isEqualToString: @"NSCell"])
{
return NO;
}
else if([className isEqualToString: @"NSDocument"])
{
return NO;
}
else if([className isEqualToString: @"NSDocumentController"])
{
return NO;
}
else if([className isEqualToString: @"NSFontManager"])
{
return NO;
}
else if([className isEqualToString: @"NSHelpManager"])
{
return NO;
}
else if([className isEqualToString: @"NSImage"])
{
return NO;
}
else if([self isSuperclass: @"NSMenuItem" linkedToClass: className] ||
[className isEqualToString: @"NSMenuItem"])
{
return NO;
}
else if([className isEqualToString: @"NSResponder"])
{
return NO;
}
else if([self isSuperclass: @"NSSound" linkedToClass: className] ||
[className isEqualToString: @"NSSound"])
{
return NO;
}
else if([self isSuperclass: @"NSTableColumn" linkedToClass: className] ||
[className isEqualToString: @"NSTableColumn"])
{
return NO;
}
else if([self isSuperclass: @"NSTableViewItem" linkedToClass: className] ||
[className isEqualToString: @"NSTableViewItem"])
{
return NO;
}
else if([self isSuperclass: @"NSWindow" linkedToClass: className] ||
[className isEqualToString: @"NSWindow"])
{
return NO;
}
else if([self isSuperclass: @"FirstResponder" linkedToClass: className] ||
[className isEqualToString: @"FirstResponder"])
{
// special case, FirstResponder.
return NO;
}
return YES;
}
- (NSString *) description
{
return [NSString stringWithFormat: @"<%s: %lx> = %@",

View file

@ -132,6 +132,7 @@
- (id) instantiateClass: (id)sender;
- (void) selectClassWithObject: (id)obj;
- (void) selectClass: (NSString *)className;
- (BOOL) classIsSelected;
// sound & image support
- (id) openSound: (id)sender;
@ -139,7 +140,6 @@
// Internals support
- (void) rebuildObjToNameMapping;
- (id) parseHeader: (NSString *)headerPath;
- (BOOL) removeConnectionsWithLabel: (NSString *)name
forClassNamed: (NSString *)className
isAction: (BOOL)action;

File diff suppressed because it is too large Load diff

View file

@ -34,7 +34,6 @@
@interface GormSoundInspector : IBInspector
{
id *_currentSound;
GormSoundView *soundView;
}
- (void) stop: (id)sender;

View file

@ -68,13 +68,12 @@
- (void) setObject: (id)anObject
{
// if its not nil, load it...
if(anObject != nil && anObject != _currentSound)
if(anObject != nil)
{
if([anObject isKindOfClass: [GormSound class]])
{
id snd;
_currentSound = anObject;
NSDebugLog(@"Sound inspector notified: %@",anObject);
snd = AUTORELEASE([[NSSound alloc] initWithContentsOfFile: [anObject soundPath]
byReference: YES]);