1999-12-20 14:20:06 +00:00
|
|
|
/* GormClassManager.m
|
|
|
|
*
|
|
|
|
* Copyright (C) 1999 Free Software Foundation, Inc.
|
|
|
|
*
|
|
|
|
* Author: Richard Frith-Macdonald <richard@brainstrom.co.uk>
|
2002-07-14 23:54:05 +00:00
|
|
|
* Author: Gregory John Casamento <greg_casamento@yahoo.com>
|
|
|
|
* Date: 1999, 2002
|
2001-05-08 09:43:11 +00:00
|
|
|
*
|
1999-12-20 14:20:06 +00:00
|
|
|
* This file is part of GNUstep.
|
2001-05-08 09:43:11 +00:00
|
|
|
*
|
1999-12-20 14:20:06 +00:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
2007-11-05 23:44:36 +00:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1999-12-20 14:20:06 +00:00
|
|
|
* (at your option) any later version.
|
2001-05-08 09:43:11 +00:00
|
|
|
*
|
1999-12-20 14:20:06 +00:00
|
|
|
* This program 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 General Public License for more details.
|
2001-05-08 09:43:11 +00:00
|
|
|
*
|
1999-12-20 14:20:06 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2005-05-26 03:37:38 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
1999-12-20 14:20:06 +00:00
|
|
|
*/
|
|
|
|
|
2023-07-04 20:00:18 +00:00
|
|
|
#import <Foundation/Foundation.h>
|
2019-11-03 01:57:39 +00:00
|
|
|
|
2023-07-04 20:00:18 +00:00
|
|
|
#import <InterfaceBuilder/InterfaceBuilder.h>
|
|
|
|
#import <GormObjCHeaderParser/GormObjCHeaderParser.h>
|
2019-11-03 01:57:39 +00:00
|
|
|
|
2023-07-04 20:00:18 +00:00
|
|
|
#import "GormPrivate.h"
|
|
|
|
#import "GormCustomView.h"
|
|
|
|
#import "GormDocument.h"
|
|
|
|
#import "GormFilesOwner.h"
|
|
|
|
#import "GormPalettesManager.h"
|
|
|
|
#import "GormAbstractDelegate.h"
|
2004-11-27 10:56:40 +00:00
|
|
|
|
2005-01-09 06:40:05 +00:00
|
|
|
/**
|
|
|
|
* Just a few definitions to start things out. To increase efficiency,
|
|
|
|
* so that Gorm doesn't need to constantly derive the method list for
|
|
|
|
* each class, it is necessary to cache some information. Here is the
|
|
|
|
* way it works.
|
|
|
|
*
|
|
|
|
* Actions = All actions on that class, excluding superclass methods.
|
|
|
|
* AllActions = All actions on that class including superclass methods.
|
|
|
|
* ExtraActions = All actions added during this session.
|
|
|
|
*
|
|
|
|
* Outlets = All actions on that class, excluding superclass methods.
|
|
|
|
* AllOutlets = All actions on that class including superclass methods.
|
|
|
|
* ExtraOutlets = All actions added during this session.
|
|
|
|
*/
|
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
/** Private methods not accesible from outside */
|
|
|
|
@interface GormClassManager (Private)
|
1999-12-21 11:38:49 +00:00
|
|
|
- (NSMutableDictionary*) classInfoForClassName: (NSString*)className;
|
2002-10-13 06:04:05 +00:00
|
|
|
- (NSMutableDictionary*) classInfoForObject: (id)anObject;
|
2004-11-04 06:46:26 +00:00
|
|
|
- (void) touch;
|
|
|
|
- (void) convertDictionary: (NSMutableDictionary *)dict;
|
1999-12-21 11:38:49 +00:00
|
|
|
@end
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
@interface NSMutableArray (Private)
|
2004-12-09 00:56:57 +00:00
|
|
|
- (void) mergeObject: (id)object;
|
2004-11-07 19:32:57 +00:00
|
|
|
- (void) mergeObjectsFromArray: (NSArray *)array;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSMutableArray (Private)
|
2004-12-09 00:56:57 +00:00
|
|
|
- (void) mergeObject: (id)object
|
|
|
|
{
|
|
|
|
if ([self containsObject: object] == NO)
|
|
|
|
{
|
|
|
|
[self addObject: object];
|
|
|
|
[self sortUsingSelector: @selector(compare:)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
- (void) mergeObjectsFromArray: (NSArray *)array
|
|
|
|
{
|
|
|
|
id obj = nil;
|
|
|
|
|
|
|
|
if(array != nil)
|
|
|
|
{
|
2005-01-09 06:40:05 +00:00
|
|
|
NSEnumerator *enumerator = [array objectEnumerator];
|
2004-11-07 19:32:57 +00:00
|
|
|
while ((obj = [enumerator nextObject]) != nil)
|
|
|
|
{
|
2004-12-09 00:56:57 +00:00
|
|
|
[self mergeObject: obj];
|
2004-11-07 19:32:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
1999-12-20 14:20:06 +00:00
|
|
|
@implementation GormClassManager
|
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
- (id) initWithDocument: (id)aDocument
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if (self != nil)
|
|
|
|
{
|
2023-06-14 10:49:47 +00:00
|
|
|
NSBundle *bundle = [NSBundle bundleForClass: [self class]];
|
2004-11-04 06:46:26 +00:00
|
|
|
NSString *path;
|
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
_document = aDocument; // the _document retains us, this is for convenience
|
2004-11-04 06:46:26 +00:00
|
|
|
|
|
|
|
path = [bundle pathForResource: @"ClassInformation" ofType: @"plist"];
|
|
|
|
if (path == nil)
|
|
|
|
{
|
|
|
|
NSLog(@"ClassInformation.plist missing from resources");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-06-17 16:14:48 +00:00
|
|
|
GormPalettesManager *palettesManager = [(id<GormAppDelegate>)[NSApp delegate] palettesManager];
|
2005-04-16 21:25:33 +00:00
|
|
|
NSDictionary *importedClasses = [palettesManager importedClasses];
|
|
|
|
NSEnumerator *en = [importedClasses objectEnumerator];
|
|
|
|
NSDictionary *description = nil;
|
2005-05-01 05:16:48 +00:00
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
// load the classes, initialize the custom class array and map..
|
2005-05-01 05:16:48 +00:00
|
|
|
if([self loadFromFile: path])
|
2005-04-16 21:25:33 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *classDict = [_classInformation objectForKey: @"FirstResponder"];
|
2005-05-01 05:16:48 +00:00
|
|
|
NSMutableArray *firstResponderActions = [classDict objectForKey: @"Actions"];
|
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
_customClasses = [[NSMutableArray alloc] initWithCapacity: 1];
|
|
|
|
_customClassMap = [[NSMutableDictionary alloc] initWithCapacity: 10];
|
|
|
|
_categoryClasses = [[NSMutableArray alloc] initWithCapacity: 1];
|
2005-05-01 05:16:48 +00:00
|
|
|
|
|
|
|
// add the imported classes to the class information list...
|
2023-07-08 17:30:13 +00:00
|
|
|
[_classInformation addEntriesFromDictionary: importedClasses];
|
2005-05-01 05:16:48 +00:00
|
|
|
|
|
|
|
// add all of the actions to the FirstResponder
|
|
|
|
while((description = [en nextObject]) != nil)
|
2005-04-16 21:25:33 +00:00
|
|
|
{
|
2005-05-01 05:16:48 +00:00
|
|
|
NSArray *actions = [description objectForKey: @"Actions"];
|
|
|
|
NSEnumerator *aen = [actions objectEnumerator];
|
|
|
|
NSString *actionName = nil;
|
|
|
|
|
|
|
|
// add the actions to the first responder...
|
|
|
|
while((actionName = [aen nextObject]) != nil)
|
|
|
|
{
|
|
|
|
if(![firstResponderActions containsObject: actionName])
|
|
|
|
{
|
|
|
|
[firstResponderActions addObject: [actionName copy]];
|
|
|
|
}
|
|
|
|
}
|
2005-04-16 21:25:33 +00:00
|
|
|
}
|
2005-05-01 05:16:48 +00:00
|
|
|
|
|
|
|
// incorporate the added actions into the list and sort.
|
|
|
|
[self allActionsForClassNamed: @"FirstResponder"];
|
2005-04-16 21:25:33 +00:00
|
|
|
}
|
2004-11-04 06:46:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) touch
|
2003-06-06 06:24:46 +00:00
|
|
|
{
|
2003-06-08 04:38:59 +00:00
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
postNotificationName: GormDidModifyClassNotification
|
|
|
|
object: self];
|
2005-01-09 06:40:05 +00:00
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
[_document touch];
|
2003-06-06 06:24:46 +00:00
|
|
|
}
|
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
- (void) convertDictionary: (NSMutableDictionary *)dict
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
[dict removeObjectsForKeys: [_classInformation allKeys]];
|
2004-11-04 06:46:26 +00:00
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSString *) uniqueClassNameFrom: (NSString *)name
|
|
|
|
{
|
|
|
|
NSString *search = [NSString stringWithString: name];
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger i = 1;
|
2004-12-14 11:13:59 +00:00
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
while([_classInformation objectForKey: search])
|
2004-12-14 11:13:59 +00:00
|
|
|
{
|
2014-05-28 07:02:41 +00:00
|
|
|
search = [name stringByAppendingString: [NSString stringWithFormat: @"%ld",(long)i++]];
|
2004-12-14 11:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return search;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) addClassWithSuperClassName: (NSString*)name
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
if (([self isRootClass: name] || [_classInformation objectForKey: name] != nil)
|
2005-05-21 15:10:14 +00:00
|
|
|
&& [name isEqual: @"FirstResponder"] == NO)
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *classInfo;
|
|
|
|
NSMutableArray *outlets;
|
|
|
|
NSMutableArray *actions;
|
2004-12-14 11:13:59 +00:00
|
|
|
NSString *className = [self uniqueClassNameFrom: @"NewClass"];
|
2001-05-08 09:43:11 +00:00
|
|
|
|
|
|
|
classInfo = [[NSMutableDictionary alloc] initWithCapacity: 3];
|
|
|
|
outlets = [[NSMutableArray alloc] initWithCapacity: 0];
|
|
|
|
actions = [[NSMutableArray alloc] initWithCapacity: 0];
|
|
|
|
|
|
|
|
[classInfo setObject: outlets forKey: @"Outlets"];
|
|
|
|
[classInfo setObject: actions forKey: @"Actions"];
|
|
|
|
[classInfo setObject: name forKey: @"Super"];
|
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
[_classInformation setObject: classInfo forKey: className];
|
|
|
|
[_customClasses addObject: className];
|
2002-07-13 19:12:15 +00:00
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2004-05-14 06:32:24 +00:00
|
|
|
|
2003-06-30 02:15:00 +00:00
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
postNotificationName: GormDidAddClassNotification
|
|
|
|
object: self];
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
return className;
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
2004-12-14 11:13:59 +00:00
|
|
|
|
|
|
|
return nil;
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
|
|
|
|
2002-07-14 23:54:05 +00:00
|
|
|
- (NSString *) addNewActionToClassNamed: (NSString *)name
|
|
|
|
{
|
2004-11-07 19:32:57 +00:00
|
|
|
NSArray *combined = [self allActionsForClassNamed: name];
|
2004-11-04 03:11:38 +00:00
|
|
|
NSString *newAction = @"newAction";
|
|
|
|
NSString *search = [newAction stringByAppendingString: @":"];
|
|
|
|
NSString *new = nil;
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger i = 1;
|
2003-06-06 06:24:46 +00:00
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
while ([combined containsObject: search])
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
2014-05-28 07:02:41 +00:00
|
|
|
new = [newAction stringByAppendingFormat: @"%ld", (long)i++];
|
2002-07-14 23:54:05 +00:00
|
|
|
search = [new stringByAppendingString: @":"];
|
|
|
|
}
|
|
|
|
|
|
|
|
[self addAction: search forClassNamed: name];
|
|
|
|
return search;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) addNewOutletToClassNamed: (NSString *)name
|
|
|
|
{
|
2004-11-07 19:32:57 +00:00
|
|
|
NSArray *combined = [self allOutletsForClassNamed: name];
|
2004-11-04 03:11:38 +00:00
|
|
|
NSString *newOutlet = @"newOutlet";
|
|
|
|
NSString *new = newOutlet;
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger i = 1;
|
2002-07-14 23:54:05 +00:00
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
while ([combined containsObject: new])
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
2014-05-28 07:02:41 +00:00
|
|
|
new = [newOutlet stringByAppendingFormat: @"%ld", (long)i++];
|
2002-07-14 23:54:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[self addOutlet: new forClassNamed: name];
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (BOOL) addClassNamed: (NSString *)className
|
|
|
|
withSuperClassNamed: (NSString *)superClassName
|
|
|
|
withActions: (NSArray *)actions
|
|
|
|
withOutlets: (NSArray *)outlets
|
2004-07-12 04:16:09 +00:00
|
|
|
{
|
2004-12-14 11:13:59 +00:00
|
|
|
return [self addClassNamed: className
|
|
|
|
withSuperClassNamed: superClassName
|
|
|
|
withActions: actions
|
|
|
|
withOutlets: outlets
|
2004-07-12 04:16:09 +00:00
|
|
|
isCustom: YES];
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (BOOL) addClassNamed: (NSString *)className
|
|
|
|
withSuperClassNamed: (NSString *)superClassName
|
|
|
|
withActions: (NSArray *)actions
|
|
|
|
withOutlets: (NSArray *)outlets
|
2004-07-12 04:16:09 +00:00
|
|
|
isCustom: (BOOL) isCustom
|
2001-12-19 07:13:54 +00:00
|
|
|
{
|
|
|
|
BOOL result = NO;
|
2004-12-14 11:13:59 +00:00
|
|
|
NSString *classNameCopy = [NSString stringWithString: className];
|
2006-09-29 02:28:49 +00:00
|
|
|
NSString *superClassNameCopy = (superClassName != nil)?[NSString stringWithString: superClassName]:nil;
|
|
|
|
NSMutableArray *actionsCopy = (actions != nil)?[NSMutableArray arrayWithArray: actions]:[NSMutableArray array];
|
|
|
|
NSMutableArray *outletsCopy = (outlets != nil)?[NSMutableArray arrayWithArray: outlets]:[NSMutableArray array];
|
2004-12-14 11:13:59 +00:00
|
|
|
|
|
|
|
// We make an autoreleased copy of all of the inputs. This prevents changes
|
|
|
|
// to the original objects from reflecting here. GJC
|
2001-12-19 07:13:54 +00:00
|
|
|
|
2005-07-13 06:19:16 +00:00
|
|
|
if ([self isRootClass: superClassNameCopy] ||
|
2023-07-08 17:30:13 +00:00
|
|
|
([_classInformation objectForKey: superClassNameCopy] != nil &&
|
2004-12-15 02:33:17 +00:00
|
|
|
[superClassNameCopy isEqualToString: @"FirstResponder"] == NO))
|
2001-12-19 07:13:54 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *classInfo;
|
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
if (![_classInformation objectForKey: classNameCopy])
|
2001-12-19 07:13:54 +00:00
|
|
|
{
|
2004-12-14 11:13:59 +00:00
|
|
|
NSEnumerator *e = [actionsCopy objectEnumerator];
|
2003-06-07 05:21:16 +00:00
|
|
|
id action = nil;
|
2004-12-14 11:13:59 +00:00
|
|
|
NSArray *superActions = [self allActionsForClassNamed: superClassNameCopy];
|
|
|
|
NSArray *superOutlets = [self allOutletsForClassNamed: superClassNameCopy];
|
2003-06-07 05:21:16 +00:00
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2001-12-19 07:13:54 +00:00
|
|
|
classInfo = [[NSMutableDictionary alloc] initWithCapacity: 3];
|
2004-12-14 11:13:59 +00:00
|
|
|
|
|
|
|
// if an outlet/action is defined on the superclass before this
|
|
|
|
// class is added, the superclass' entry takes precedence.
|
|
|
|
[actionsCopy removeObjectsInArray: superActions];
|
|
|
|
[outletsCopy removeObjectsInArray: superOutlets];
|
2001-12-19 07:13:54 +00:00
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
[classInfo setObject: outletsCopy forKey: @"Outlets"];
|
|
|
|
[classInfo setObject: actionsCopy forKey: @"Actions"];
|
2006-09-29 02:28:49 +00:00
|
|
|
if(superClassNameCopy != nil)
|
|
|
|
{
|
|
|
|
[classInfo setObject: superClassNameCopy forKey: @"Super"];
|
|
|
|
}
|
2023-07-08 17:30:13 +00:00
|
|
|
[_classInformation setObject: classInfo forKey: classNameCopy];
|
2004-07-12 04:16:09 +00:00
|
|
|
|
|
|
|
// if it's a custom class add it to the list.
|
|
|
|
if(isCustom)
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
[_customClasses addObject: classNameCopy];
|
2004-07-12 04:16:09 +00:00
|
|
|
}
|
2003-06-07 05:21:16 +00:00
|
|
|
|
|
|
|
// copy all actions from the class imported to the first responder
|
2003-06-08 04:38:59 +00:00
|
|
|
while((action = [e nextObject]))
|
2003-06-07 05:21:16 +00:00
|
|
|
{
|
2004-11-07 19:32:57 +00:00
|
|
|
[self addAction: action forClassNamed: @"FirstResponder"];
|
2003-06-07 05:21:16 +00:00
|
|
|
}
|
|
|
|
|
2001-12-19 07:13:54 +00:00
|
|
|
result = YES;
|
2003-06-30 02:15:00 +00:00
|
|
|
|
|
|
|
// post the notification
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
postNotificationName: GormDidAddClassNotification
|
|
|
|
object: self];
|
2001-12-19 07:13:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-12-27 22:16:12 +00:00
|
|
|
NSDebugLog(@"Class already exists");
|
2001-12-19 07:13:54 +00:00
|
|
|
result = NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (void) addAction: (NSString *)anAction forObject: (id)anObject
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
2004-04-27 05:30:52 +00:00
|
|
|
[self addAction: anAction forClassNamed: [anObject className]];
|
1999-12-21 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2003-08-24 17:10:05 +00:00
|
|
|
- (void) addAction: (NSString *)action forClassNamed: (NSString *)className
|
2002-07-11 05:50:04 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: className];
|
2002-07-12 05:46:29 +00:00
|
|
|
NSMutableArray *extraActions = [info objectForKey: @"ExtraActions"];
|
2004-12-09 00:56:57 +00:00
|
|
|
NSMutableArray *allActions = [info objectForKey: @"AllActions"];
|
2003-08-24 17:10:05 +00:00
|
|
|
NSString *anAction = [action copy];
|
2004-12-09 00:56:57 +00:00
|
|
|
NSArray *subClasses = [self allSubclassesOf: className];
|
|
|
|
NSEnumerator *en = [subClasses objectEnumerator];
|
2004-04-27 05:30:52 +00:00
|
|
|
NSString *subclassName = nil;
|
2002-07-12 05:46:29 +00:00
|
|
|
|
2023-12-17 15:54:50 +00:00
|
|
|
if (action == nil
|
|
|
|
|| className == nil)
|
|
|
|
{
|
|
|
|
NSLog(@"Attempt to add nil action = %@ or className = %@ to class manager", action, className);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-12-09 00:56:57 +00:00
|
|
|
// check all
|
2003-02-13 13:32:59 +00:00
|
|
|
if ([allActions containsObject: anAction])
|
2002-07-12 05:46:29 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
|
|
|
if ([self isNonCustomClass: className])
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
if([_categoryClasses containsObject: className] == NO)
|
2004-11-07 19:32:57 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
[_categoryClasses addObject: className];
|
2004-11-07 19:32:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
if (extraActions == nil)
|
2002-07-12 05:46:29 +00:00
|
|
|
{
|
|
|
|
extraActions = [[NSMutableArray alloc] initWithCapacity: 1];
|
|
|
|
[info setObject: extraActions forKey: @"ExtraActions"];
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2004-12-09 00:56:57 +00:00
|
|
|
[extraActions mergeObject: anAction];
|
|
|
|
[allActions mergeObject: anAction];
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2003-05-25 19:08:36 +00:00
|
|
|
if(![className isEqualToString: @"FirstResponder"])
|
|
|
|
{
|
2004-11-04 06:46:26 +00:00
|
|
|
[self addAction: anAction forClassNamed: @"FirstResponder"];
|
2003-05-25 19:08:36 +00:00
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2004-04-27 05:30:52 +00:00
|
|
|
while((subclassName = [en nextObject]) != nil)
|
2004-12-09 00:56:57 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *subInfo = [_classInformation objectForKey: subclassName];
|
2004-12-09 00:56:57 +00:00
|
|
|
NSMutableArray *subAll = [subInfo objectForKey: @"AllActions"];
|
|
|
|
[subAll mergeObject: anAction];
|
2004-04-27 05:30:52 +00:00
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2004-04-27 05:30:52 +00:00
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (void) addOutlet: (NSString *)outlet forObject: (id)anObject
|
2004-04-27 05:30:52 +00:00
|
|
|
{
|
|
|
|
[self addOutlet: outlet forClassNamed: [anObject className]];
|
2002-07-11 05:50:04 +00:00
|
|
|
}
|
|
|
|
|
2004-12-09 00:56:57 +00:00
|
|
|
- (void) addOutlet: (NSString *)outlet forClassNamed: (NSString *)className
|
2002-07-11 05:50:04 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: className];
|
2002-07-12 05:46:29 +00:00
|
|
|
NSMutableArray *extraOutlets = [info objectForKey: @"ExtraOutlets"];
|
2004-12-09 00:56:57 +00:00
|
|
|
NSMutableArray *allOutlets = [info objectForKey: @"AllOutlets"];
|
2004-04-27 05:30:52 +00:00
|
|
|
NSString *anOutlet = [outlet copy];
|
2004-12-09 00:56:57 +00:00
|
|
|
NSArray *subClasses = [self allSubclassesOf: className];
|
|
|
|
NSEnumerator *en = [subClasses objectEnumerator];
|
2004-04-27 05:30:52 +00:00
|
|
|
NSString *subclassName = nil;
|
2004-11-07 19:32:57 +00:00
|
|
|
|
|
|
|
// check all
|
2003-02-13 13:32:59 +00:00
|
|
|
if ([allOutlets containsObject: anOutlet])
|
2002-07-12 05:46:29 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
if (extraOutlets == nil)
|
2002-07-12 05:46:29 +00:00
|
|
|
{
|
|
|
|
extraOutlets = [[NSMutableArray alloc] initWithCapacity: 1];
|
|
|
|
[info setObject: extraOutlets forKey: @"ExtraOutlets"];
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2004-12-09 00:56:57 +00:00
|
|
|
[extraOutlets mergeObject: anOutlet];
|
|
|
|
[allOutlets mergeObject: anOutlet];
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2004-04-27 05:30:52 +00:00
|
|
|
while((subclassName = [en nextObject]) != nil)
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *subInfo = [_classInformation objectForKey: subclassName];
|
2004-12-09 00:56:57 +00:00
|
|
|
NSMutableArray *subAll = [subInfo objectForKey: @"AllOutlets"];
|
|
|
|
[subAll mergeObject: anOutlet];
|
2004-04-27 05:30:52 +00:00
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2002-07-12 05:46:29 +00:00
|
|
|
}
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
- (void) replaceAction: (NSString *)oldAction
|
2004-11-07 19:32:57 +00:00
|
|
|
withAction: (NSString *)aNewAction
|
2005-11-12 21:33:26 +00:00
|
|
|
forClassNamed: (NSString *)className
|
2002-07-12 05:46:29 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: className];
|
2002-07-12 05:46:29 +00:00
|
|
|
NSMutableArray *extraActions = [info objectForKey: @"ExtraActions"];
|
2002-07-14 23:54:05 +00:00
|
|
|
NSMutableArray *actions = [info objectForKey: @"Actions"];
|
2002-07-21 04:04:18 +00:00
|
|
|
NSMutableArray *allActions = [info objectForKey: @"AllActions"];
|
2004-11-07 19:32:57 +00:00
|
|
|
NSString *newAction = AUTORELEASE([aNewAction copy]);
|
2004-04-28 01:34:12 +00:00
|
|
|
NSEnumerator *en = [[self subClassesOf: className] objectEnumerator];
|
2004-04-27 05:30:52 +00:00
|
|
|
NSString *subclassName = nil;
|
2002-07-12 05:46:29 +00:00
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
if ([allActions containsObject: newAction]
|
|
|
|
|| [extraActions containsObject: newAction])
|
2002-07-22 15:24:37 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
// replace the action in the appropriate places.
|
2003-02-13 13:32:59 +00:00
|
|
|
if ([extraActions containsObject: oldAction])
|
2002-07-12 05:46:29 +00:00
|
|
|
{
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger extra_index = [extraActions indexOfObject: oldAction];
|
2002-07-12 05:46:29 +00:00
|
|
|
[extraActions replaceObjectAtIndex: extra_index withObject: newAction];
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
|
|
|
if ([actions containsObject: oldAction])
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger actions_index = [actions indexOfObject: oldAction];
|
2002-07-14 23:54:05 +00:00
|
|
|
[actions replaceObjectAtIndex: actions_index withObject: newAction];
|
2004-11-07 19:32:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ([allActions containsObject: oldAction])
|
|
|
|
{
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger all_index = [allActions indexOfObject: oldAction];
|
2002-07-21 04:04:18 +00:00
|
|
|
[allActions replaceObjectAtIndex: all_index withObject: newAction];
|
2002-07-14 23:54:05 +00:00
|
|
|
}
|
2004-04-27 05:30:52 +00:00
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2004-05-14 06:32:24 +00:00
|
|
|
|
2004-04-27 05:30:52 +00:00
|
|
|
// add the action to all of the subclasses, in the "AllActions" section...
|
|
|
|
while((subclassName = [en nextObject]) != nil)
|
|
|
|
{
|
2004-11-07 19:32:57 +00:00
|
|
|
[self replaceAction: oldAction withAction: newAction forClassNamed: subclassName];
|
2004-04-27 05:30:52 +00:00
|
|
|
}
|
|
|
|
|
2003-05-25 19:08:36 +00:00
|
|
|
if(![className isEqualToString: @"FirstResponder"])
|
|
|
|
{
|
2004-11-04 06:46:26 +00:00
|
|
|
[self replaceAction: oldAction withAction: newAction forClassNamed: @"FirstResponder"];
|
2003-05-25 19:08:36 +00:00
|
|
|
}
|
2002-07-12 05:46:29 +00:00
|
|
|
}
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
- (void) replaceOutlet: (NSString *)oldOutlet
|
2004-11-07 19:32:57 +00:00
|
|
|
withOutlet: (NSString *)aNewOutlet
|
2005-11-12 21:33:26 +00:00
|
|
|
forClassNamed: (NSString *)className
|
2002-07-12 05:46:29 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: className];
|
2002-07-12 05:46:29 +00:00
|
|
|
NSMutableArray *extraOutlets = [info objectForKey: @"ExtraOutlets"];
|
2002-07-14 23:54:05 +00:00
|
|
|
NSMutableArray *outlets = [info objectForKey: @"Outlets"];
|
2002-07-21 04:04:18 +00:00
|
|
|
NSMutableArray *allOutlets = [info objectForKey: @"AllOutlets"];
|
2004-11-07 19:32:57 +00:00
|
|
|
NSString *newOutlet = AUTORELEASE([aNewOutlet copy]);
|
2004-04-28 01:34:12 +00:00
|
|
|
NSEnumerator *en = [[self subClassesOf: className] objectEnumerator];
|
2004-04-27 05:30:52 +00:00
|
|
|
NSString *subclassName = nil;
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
if ([allOutlets containsObject: newOutlet]
|
|
|
|
|| [extraOutlets containsObject: newOutlet])
|
2002-07-22 15:24:37 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
// replace outlets in appropriate places...
|
2003-02-13 13:32:59 +00:00
|
|
|
if ([extraOutlets containsObject: oldOutlet])
|
2002-07-12 05:46:29 +00:00
|
|
|
{
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger extraIndex = [extraOutlets indexOfObject: oldOutlet];
|
2004-11-07 19:32:57 +00:00
|
|
|
[extraOutlets replaceObjectAtIndex: extraIndex withObject: newOutlet];
|
2002-07-12 05:46:29 +00:00
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
|
|
|
if ([outlets containsObject: oldOutlet])
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger outletsIndex = [outlets indexOfObject: oldOutlet];
|
2004-11-07 19:32:57 +00:00
|
|
|
[outlets replaceObjectAtIndex: outletsIndex withObject: newOutlet];
|
|
|
|
}
|
2002-07-14 23:54:05 +00:00
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
if ([allOutlets containsObject: oldOutlet])
|
|
|
|
{
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger allIndex = [allOutlets indexOfObject: oldOutlet];
|
2004-11-07 19:32:57 +00:00
|
|
|
[allOutlets replaceObjectAtIndex: allIndex withObject: newOutlet];
|
2002-07-14 23:54:05 +00:00
|
|
|
}
|
2004-04-27 05:30:52 +00:00
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2004-05-14 06:32:24 +00:00
|
|
|
|
2004-04-27 05:30:52 +00:00
|
|
|
// add the action to all of the subclasses, in the "AllActions" section...
|
|
|
|
while((subclassName = [en nextObject]) != nil)
|
|
|
|
{
|
2004-11-07 19:32:57 +00:00
|
|
|
[self replaceOutlet: oldOutlet withOutlet: newOutlet forClassNamed: subclassName];
|
2004-04-28 01:34:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (void) removeAction: (NSString *)anAction forObject: (id)anObject
|
2004-04-28 01:34:12 +00:00
|
|
|
{
|
|
|
|
[self removeAction: anAction fromClassNamed: [anObject className]];
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (void) removeAction: (NSString *)anAction
|
2004-04-28 01:34:12 +00:00
|
|
|
fromClassNamed: (NSString *)className
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: className];
|
2004-04-28 01:34:12 +00:00
|
|
|
NSMutableArray *extraActions = [info objectForKey: @"ExtraActions"];
|
|
|
|
NSMutableArray *allActions = [info objectForKey: @"AllActions"];
|
|
|
|
NSEnumerator *en = [[self subClassesOf: className] objectEnumerator];
|
|
|
|
NSString *subclassName = nil;
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
if ([extraActions containsObject: anAction] == YES ||
|
|
|
|
[allActions containsObject: anAction] == YES)
|
2004-04-28 01:34:12 +00:00
|
|
|
{
|
|
|
|
NSString *superName = [info objectForKey: @"Super"];
|
|
|
|
|
|
|
|
if (superName != nil)
|
|
|
|
{
|
|
|
|
NSArray *superActions;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this action is new in this class (ie not overriding an
|
|
|
|
* action in a parent) then we remove it from the list of all
|
|
|
|
* actions that the object responds to.
|
|
|
|
*/
|
|
|
|
superActions = [self allActionsForClassNamed: superName];
|
|
|
|
if ([superActions containsObject: anAction] == NO)
|
|
|
|
{
|
|
|
|
NSMutableArray *array = [info objectForKey: @"AllActions"];
|
|
|
|
NSMutableArray *actions = [info objectForKey: @"Actions"];
|
|
|
|
[array removeObject: anAction];
|
|
|
|
[actions removeObject: anAction];
|
|
|
|
}
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
NSMutableArray *array = [info objectForKey: @"AllActions"];
|
|
|
|
NSMutableArray *actions = [info objectForKey: @"Actions"];
|
|
|
|
[array removeObject: anAction];
|
|
|
|
[actions removeObject: anAction];
|
|
|
|
}
|
|
|
|
|
2004-04-28 01:34:12 +00:00
|
|
|
[extraActions removeObject: anAction];
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2004-04-28 01:34:12 +00:00
|
|
|
}
|
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
if([_categoryClasses containsObject: className] && [extraActions count] == 0)
|
2004-11-07 19:32:57 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
[_categoryClasses removeObject: className];
|
2004-11-07 19:32:57 +00:00
|
|
|
}
|
|
|
|
|
2004-04-28 01:34:12 +00:00
|
|
|
if(![className isEqualToString: @"FirstResponder"])
|
|
|
|
{
|
2004-11-04 06:46:26 +00:00
|
|
|
[self removeAction: anAction fromClassNamed: @"FirstResponder"];
|
2004-04-28 01:34:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while((subclassName = [en nextObject]) != nil)
|
|
|
|
{
|
|
|
|
[self removeAction: anAction fromClassNamed: subclassName];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (void) removeOutlet: (NSString *)anOutlet forObject: (id)anObject
|
2004-04-28 01:34:12 +00:00
|
|
|
{
|
|
|
|
[self removeOutlet: anOutlet fromClassNamed: [anObject className]];
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (void) removeOutlet: (NSString *)anOutlet fromClassNamed: (NSString *)className
|
2004-04-28 01:34:12 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: className];
|
2004-04-28 01:34:12 +00:00
|
|
|
NSMutableArray *extraOutlets = [info objectForKey: @"ExtraOutlets"];
|
|
|
|
NSMutableArray *allOutlets = [info objectForKey: @"AllOutlets"];
|
|
|
|
NSEnumerator *en = [[self subClassesOf: className] objectEnumerator];
|
|
|
|
NSString *subclassName = nil;
|
|
|
|
|
|
|
|
if ([extraOutlets containsObject: anOutlet] == YES
|
|
|
|
|| [allOutlets containsObject: anOutlet] == YES)
|
|
|
|
{
|
|
|
|
NSString *superName = [info objectForKey: @"Super"];
|
|
|
|
|
|
|
|
if (superName != nil)
|
|
|
|
{
|
|
|
|
NSArray *superOutlets;
|
|
|
|
|
|
|
|
// remove the outlet from the other arrays...
|
|
|
|
superOutlets = [self allOutletsForClassNamed: superName];
|
|
|
|
if ([superOutlets containsObject: anOutlet] == NO)
|
|
|
|
{
|
|
|
|
NSMutableArray *array = [info objectForKey: @"AllOutlets"];
|
|
|
|
NSMutableArray *actions = [info objectForKey: @"Outlets"];
|
|
|
|
[array removeObject: anOutlet];
|
|
|
|
[actions removeObject: anOutlet];
|
|
|
|
}
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
NSMutableArray *array = [info objectForKey: @"AllOutlets"];
|
|
|
|
NSMutableArray *actions = [info objectForKey: @"Outlets"];
|
|
|
|
[array removeObject: anOutlet];
|
|
|
|
[actions removeObject: anOutlet];
|
|
|
|
}
|
|
|
|
|
2004-04-28 01:34:12 +00:00
|
|
|
[extraOutlets removeObject: anOutlet];
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2004-04-28 01:34:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while((subclassName = [en nextObject]) != nil)
|
|
|
|
{
|
|
|
|
[self removeOutlet: anOutlet fromClassNamed: subclassName];
|
2004-04-27 05:30:52 +00:00
|
|
|
}
|
2002-07-11 05:50:04 +00:00
|
|
|
}
|
|
|
|
|
2004-04-28 01:34:12 +00:00
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSArray *) allActionsForObject: (id)obj
|
1999-12-20 14:20:06 +00:00
|
|
|
{
|
|
|
|
NSString *className;
|
|
|
|
NSArray *actions;
|
2002-10-13 06:04:05 +00:00
|
|
|
Class theClass = [obj class];
|
|
|
|
NSString *customClassName = [self customClassForObject: obj];
|
2003-01-09 03:39:27 +00:00
|
|
|
|
|
|
|
NSDebugLog(@"** ACTIONS");
|
2003-01-08 05:54:20 +00:00
|
|
|
NSDebugLog(@"Object: %@",obj);
|
|
|
|
NSDebugLog(@"Custom class: %@",customClassName);
|
2003-02-13 13:32:59 +00:00
|
|
|
if (customClassName != nil)
|
2002-10-13 06:04:05 +00:00
|
|
|
{
|
|
|
|
// if the object has been mapped to a custom class, then
|
|
|
|
// get the information for it.
|
|
|
|
className = customClassName;
|
|
|
|
}
|
|
|
|
else if (theClass == [GormFirstResponder class])
|
1999-12-20 15:21:26 +00:00
|
|
|
{
|
2002-01-29 22:41:02 +00:00
|
|
|
className = @"FirstResponder";
|
1999-12-20 15:21:26 +00:00
|
|
|
}
|
2002-01-29 22:41:02 +00:00
|
|
|
else if (theClass == [GormFilesOwner class])
|
1999-12-20 15:21:26 +00:00
|
|
|
{
|
|
|
|
className = [(GormFilesOwner*)obj className];
|
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
else if ([obj isKindOfClass: [GSNibItem class]] == YES)
|
|
|
|
{
|
|
|
|
// this adds support for custom objects
|
2002-10-13 06:04:05 +00:00
|
|
|
className = [obj className];
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
|
|
|
else if ([obj isKindOfClass: [GormClassProxy class]] == YES)
|
|
|
|
{
|
|
|
|
// this adds support for class proxies
|
2002-10-13 06:04:05 +00:00
|
|
|
className = [obj className];
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
2001-10-03 17:38:46 +00:00
|
|
|
else if ([obj isKindOfClass: [GormCustomView class]] == YES)
|
|
|
|
{
|
|
|
|
// this adds support for custom views
|
2002-10-13 06:04:05 +00:00
|
|
|
className = [obj className];
|
2001-10-03 17:38:46 +00:00
|
|
|
}
|
1999-12-20 15:21:26 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
className = NSStringFromClass(theClass);
|
|
|
|
}
|
1999-12-20 14:20:06 +00:00
|
|
|
if (className == nil)
|
|
|
|
{
|
2004-05-01 11:07:12 +00:00
|
|
|
// NSLog(@"attempt to get actions for non-existent class (%@)",
|
|
|
|
// [obj class]);
|
1999-12-20 14:20:06 +00:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
actions = [self allActionsForClassNamed: className];
|
2010-09-16 05:04:00 +00:00
|
|
|
while (actions == nil && (theClass = class_getSuperclass(theClass)) != nil
|
1999-12-20 14:20:06 +00:00
|
|
|
&& theClass != [NSObject class])
|
|
|
|
{
|
|
|
|
className = NSStringFromClass(theClass);
|
|
|
|
actions = [self allActionsForClassNamed: className];
|
|
|
|
}
|
2003-01-08 05:54:20 +00:00
|
|
|
|
|
|
|
NSDebugLog(@"class=%@ actions=%@",className,actions);
|
1999-12-20 14:20:06 +00:00
|
|
|
return actions;
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSArray *) allActionsForClassNamed: (NSString *)className
|
1999-12-20 14:20:06 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: className];
|
1999-12-20 14:20:06 +00:00
|
|
|
|
|
|
|
if (info != nil)
|
|
|
|
{
|
|
|
|
NSMutableArray *allActions = [info objectForKey: @"AllActions"];
|
|
|
|
|
|
|
|
if (allActions == nil)
|
|
|
|
{
|
|
|
|
NSString *superName = [info objectForKey: @"Super"];
|
|
|
|
NSArray *actions = [info objectForKey: @"Actions"];
|
2004-11-07 19:32:57 +00:00
|
|
|
NSArray *extraActions = [info objectForKey: @"ExtraActions"];
|
1999-12-20 14:20:06 +00:00
|
|
|
NSArray *superActions;
|
|
|
|
|
2005-05-01 05:16:48 +00:00
|
|
|
if (superName == nil || [className isEqual: @"FirstResponder"])
|
1999-12-20 14:20:06 +00:00
|
|
|
{
|
|
|
|
superActions = nil;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
superActions = [self allActionsForClassNamed: superName];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (superActions == nil)
|
|
|
|
{
|
|
|
|
if (actions == nil)
|
|
|
|
{
|
2005-06-17 04:41:24 +00:00
|
|
|
allActions = [[NSMutableArray alloc] init];
|
1999-12-20 14:20:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allActions = [actions mutableCopy];
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
|
|
|
[allActions mergeObjectsFromArray: extraActions];
|
1999-12-20 14:20:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allActions = [superActions mutableCopy];
|
2004-11-07 19:32:57 +00:00
|
|
|
[allActions mergeObjectsFromArray: actions];
|
|
|
|
[allActions mergeObjectsFromArray: extraActions];
|
1999-12-20 14:20:06 +00:00
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
1999-12-20 14:20:06 +00:00
|
|
|
[info setObject: allActions forKey: @"AllActions"];
|
2004-11-07 19:32:57 +00:00
|
|
|
RELEASE(allActions);
|
1999-12-20 14:20:06 +00:00
|
|
|
}
|
2004-06-26 12:19:18 +00:00
|
|
|
return AUTORELEASE([allActions copy]);
|
1999-12-20 14:20:06 +00:00
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSArray *) allCustomClassNames
|
2003-08-24 17:10:05 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
// return [_customClassMap allKeys];
|
|
|
|
return _customClasses;
|
2003-08-24 17:10:05 +00:00
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSArray *) allClassNames
|
1999-12-21 08:13:35 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
return [[_classInformation allKeys] sortedArrayUsingSelector: @selector(compare:)];
|
1999-12-21 08:13:35 +00:00
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSArray *) allOutletsForObject: (id)obj
|
1999-12-20 14:20:06 +00:00
|
|
|
{
|
|
|
|
NSString *className;
|
|
|
|
NSArray *outlets;
|
1999-12-20 15:21:26 +00:00
|
|
|
Class theClass = [obj class];
|
2002-10-13 06:04:05 +00:00
|
|
|
NSString *customClassName = [self customClassForObject: obj];
|
1999-12-20 15:21:26 +00:00
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
if (customClassName != nil)
|
2002-10-13 06:04:05 +00:00
|
|
|
{
|
|
|
|
// if the object has been mapped to a custom class, then
|
|
|
|
// get the information for it.
|
|
|
|
className = customClassName;
|
|
|
|
}
|
|
|
|
else if (theClass == [GormFirstResponder class])
|
1999-12-20 15:21:26 +00:00
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
2002-10-13 06:04:05 +00:00
|
|
|
else if (theClass == [GormFilesOwner class])
|
1999-12-20 15:21:26 +00:00
|
|
|
{
|
|
|
|
className = [(GormFilesOwner*)obj className];
|
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
else if ([obj isKindOfClass: [GSNibItem class]] == YES)
|
|
|
|
{
|
|
|
|
// this adds support for custom objects
|
|
|
|
className = [(id)obj className];
|
|
|
|
}
|
|
|
|
else if ([obj isKindOfClass: [GormClassProxy class]] == YES)
|
|
|
|
{
|
|
|
|
// this adds support for class proxies
|
|
|
|
className = [(id)obj className];
|
|
|
|
}
|
2001-10-03 17:38:46 +00:00
|
|
|
else if ([obj isKindOfClass: [GormCustomView class]] == YES)
|
|
|
|
{
|
|
|
|
// this adds support for custom views
|
|
|
|
className = [(id)obj className];
|
|
|
|
}
|
1999-12-20 15:21:26 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
className = NSStringFromClass(theClass);
|
|
|
|
}
|
1999-12-20 14:20:06 +00:00
|
|
|
|
|
|
|
if (className == nil)
|
|
|
|
{
|
2002-09-10 03:00:12 +00:00
|
|
|
NSLog(@"attempt to get outlets for non-existent class (%@)",
|
|
|
|
[obj class]);
|
1999-12-20 14:20:06 +00:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
outlets = [self allOutletsForClassNamed: className];
|
2010-09-16 05:04:00 +00:00
|
|
|
while (outlets == nil && (theClass = class_getSuperclass(theClass)) != nil
|
1999-12-20 14:20:06 +00:00
|
|
|
&& theClass != [NSObject class])
|
|
|
|
{
|
|
|
|
className = NSStringFromClass(theClass);
|
|
|
|
outlets = [self allOutletsForClassNamed: className];
|
|
|
|
}
|
|
|
|
return outlets;
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSArray *) allOutletsForClassNamed: (NSString *)className;
|
1999-12-20 14:20:06 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: className];
|
1999-12-20 14:20:06 +00:00
|
|
|
|
|
|
|
if (info != nil)
|
|
|
|
{
|
|
|
|
NSMutableArray *allOutlets = [info objectForKey: @"AllOutlets"];
|
|
|
|
|
|
|
|
if (allOutlets == nil)
|
|
|
|
{
|
|
|
|
NSString *superName = [info objectForKey: @"Super"];
|
|
|
|
NSArray *outlets = [info objectForKey: @"Outlets"];
|
2004-11-07 19:32:57 +00:00
|
|
|
NSArray *extraOutlets = [info objectForKey: @"ExtraOutlets"];
|
1999-12-20 14:20:06 +00:00
|
|
|
NSArray *superOutlets;
|
|
|
|
|
|
|
|
if (superName == nil)
|
|
|
|
{
|
|
|
|
superOutlets = nil;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
superOutlets = [self allOutletsForClassNamed: superName];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (superOutlets == nil)
|
|
|
|
{
|
|
|
|
if (outlets == nil)
|
|
|
|
{
|
2005-06-17 04:41:24 +00:00
|
|
|
allOutlets = [[NSMutableArray alloc] init];
|
1999-12-20 14:20:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allOutlets = [outlets mutableCopy];
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
|
|
|
[allOutlets mergeObjectsFromArray: extraOutlets];
|
1999-12-20 14:20:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allOutlets = [superOutlets mutableCopy];
|
2004-11-07 19:32:57 +00:00
|
|
|
[allOutlets mergeObjectsFromArray: outlets];
|
|
|
|
[allOutlets mergeObjectsFromArray: extraOutlets];
|
1999-12-20 14:20:06 +00:00
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
1999-12-20 14:20:06 +00:00
|
|
|
[info setObject: allOutlets forKey: @"AllOutlets"];
|
2004-11-07 19:32:57 +00:00
|
|
|
RELEASE(allOutlets);
|
1999-12-20 14:20:06 +00:00
|
|
|
}
|
|
|
|
return AUTORELEASE([allOutlets copy]);
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSMutableDictionary*) classInfoForClassName: (NSString *)className
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *info;
|
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
info = [_classInformation objectForKey: className];
|
1999-12-21 11:38:49 +00:00
|
|
|
if (info == nil)
|
|
|
|
{
|
|
|
|
Class theClass = NSClassFromString(className);
|
|
|
|
|
|
|
|
if (theClass != nil)
|
|
|
|
{
|
2010-09-16 05:04:00 +00:00
|
|
|
theClass = class_getSuperclass(theClass);
|
1999-12-21 11:38:49 +00:00
|
|
|
if (theClass != nil && theClass != [NSObject class])
|
|
|
|
{
|
|
|
|
NSString *name;
|
|
|
|
NSMutableDictionary *dict;
|
|
|
|
|
|
|
|
name = NSStringFromClass(theClass);
|
|
|
|
dict = [self classInfoForClassName: name];
|
|
|
|
if (dict != nil)
|
|
|
|
{
|
|
|
|
id o;
|
|
|
|
|
|
|
|
info = [[NSMutableDictionary alloc] initWithCapacity: 3];
|
|
|
|
[info setObject: name forKey: @"Super"];
|
|
|
|
o = [[self allActionsForClassNamed: name] mutableCopy];
|
|
|
|
[info setObject: o forKey: @"AllActions"];
|
|
|
|
o = [[self allOutletsForClassNamed: name] mutableCopy];
|
|
|
|
[info setObject: o forKey: @"AllOutlets"];
|
2023-07-08 17:30:13 +00:00
|
|
|
[_classInformation setObject: info forKey: className];
|
1999-12-21 11:38:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
1999-12-21 11:38:49 +00:00
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
2002-10-13 06:04:05 +00:00
|
|
|
- (NSMutableDictionary*) classInfoForObject: (id)obj
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
|
|
|
NSString *className;
|
|
|
|
Class theClass = [obj class];
|
|
|
|
|
|
|
|
if (theClass == [GormFilesOwner class])
|
|
|
|
{
|
|
|
|
className = [(GormFilesOwner*)obj className];
|
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
else if ([obj isKindOfClass: [GSNibItem class]] == YES)
|
|
|
|
{
|
|
|
|
// this adds support for custom objects
|
|
|
|
className = [(id)obj className];
|
|
|
|
}
|
|
|
|
else if ([obj isKindOfClass: [GormClassProxy class]] == YES)
|
|
|
|
{
|
|
|
|
// this adds support for class proxies
|
|
|
|
className = [(id)obj className];
|
2001-10-03 17:38:46 +00:00
|
|
|
}
|
|
|
|
else if ([obj isKindOfClass: [GormCustomView class]] == YES)
|
|
|
|
{
|
|
|
|
// this adds support for custom views
|
|
|
|
className = [(id)obj className];
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
1999-12-21 11:38:49 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
className = NSStringFromClass(theClass);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (className == nil)
|
|
|
|
{
|
2002-09-10 03:00:12 +00:00
|
|
|
NSLog(@"attempt to get outlets for non-existent class (%@)",
|
|
|
|
[obj class]);
|
1999-12-21 11:38:49 +00:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
return [self classInfoForClassName: className];
|
|
|
|
}
|
|
|
|
|
2006-10-20 02:59:11 +00:00
|
|
|
- (BOOL) actionExists: (NSString *)action
|
|
|
|
onClassNamed: (NSString *)className
|
|
|
|
{
|
|
|
|
NSArray *actions = [self allActionsForClassNamed: className];
|
|
|
|
return [actions containsObject: action];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) outletExists: (NSString *)outlet
|
|
|
|
onClassNamed: (NSString *)className
|
|
|
|
{
|
|
|
|
NSArray *outlets = [self allOutletsForClassNamed: className];
|
|
|
|
return [outlets containsObject: outlet];
|
|
|
|
}
|
|
|
|
|
1999-12-20 14:20:06 +00:00
|
|
|
- (void) dealloc
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
RELEASE(_classInformation);
|
|
|
|
RELEASE(_customClassMap);
|
1999-12-20 14:20:06 +00:00
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSArray *) extraActionsForObject: (id)anObject
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *info = [self classInfoForObject: anObject];
|
|
|
|
|
|
|
|
return [info objectForKey: @"ExtraActions"];
|
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSArray *) extraOutletsForObject: (id)anObject
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *info = [self classInfoForObject: anObject];
|
|
|
|
|
|
|
|
return [info objectForKey: @"ExtraOutlets"];
|
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
|
2002-07-21 04:04:18 +00:00
|
|
|
- (void) allSubclassesOf: (NSString *)superclass
|
|
|
|
referenceClassList: (NSArray *)classList
|
|
|
|
intoArray: (NSMutableArray *)array
|
|
|
|
{
|
|
|
|
NSEnumerator *cen = [classList objectEnumerator];
|
|
|
|
id object = nil;
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
while ((object = [cen nextObject]))
|
2002-07-21 04:04:18 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *dictForClass = [_classInformation objectForKey: object];
|
2005-05-21 15:10:14 +00:00
|
|
|
NSString *superClassName = [dictForClass objectForKey: @"Super"];
|
|
|
|
if ([superClassName isEqual: superclass] ||
|
|
|
|
(superClassName == nil && superclass == nil))
|
2002-07-21 04:04:18 +00:00
|
|
|
{
|
|
|
|
[array addObject: object];
|
|
|
|
[self allSubclassesOf: object
|
2005-05-21 15:10:14 +00:00
|
|
|
referenceClassList: classList
|
|
|
|
intoArray: array];
|
2002-07-21 04:04:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-23 20:26:13 +00:00
|
|
|
- (NSArray *) allSubclassesOf: (NSString *)superClass
|
|
|
|
{
|
|
|
|
NSMutableArray *array = [NSMutableArray array];
|
|
|
|
|
2005-05-21 15:10:14 +00:00
|
|
|
[self allSubclassesOf: superClass
|
2023-07-08 17:30:13 +00:00
|
|
|
referenceClassList: [_classInformation allKeys]
|
2005-05-21 15:10:14 +00:00
|
|
|
intoArray: array];
|
2003-11-23 20:26:13 +00:00
|
|
|
|
2006-09-28 02:31:06 +00:00
|
|
|
return [array sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)];
|
2003-11-23 20:26:13 +00:00
|
|
|
}
|
|
|
|
|
2002-07-21 04:04:18 +00:00
|
|
|
- (NSArray *) allCustomSubclassesOf: (NSString *)superClass
|
|
|
|
{
|
|
|
|
NSMutableArray *array = [NSMutableArray array];
|
2005-05-21 15:10:14 +00:00
|
|
|
|
|
|
|
[self allSubclassesOf: superClass
|
2023-07-08 17:30:13 +00:00
|
|
|
referenceClassList: _customClasses
|
2005-05-21 15:10:14 +00:00
|
|
|
intoArray: array];
|
2005-04-24 15:21:12 +00:00
|
|
|
|
2006-09-28 02:31:06 +00:00
|
|
|
return [array sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)];
|
2002-07-21 04:04:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) customSubClassesOf: (NSString *)superclass
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSEnumerator *cen = [_customClasses objectEnumerator];
|
2002-07-21 04:04:18 +00:00
|
|
|
id object = nil;
|
|
|
|
NSMutableArray *subclasses = [NSMutableArray array];
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
while ((object = [cen nextObject]))
|
2002-07-21 04:04:18 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *dictForClass = [_classInformation objectForKey: object];
|
2003-02-13 13:32:59 +00:00
|
|
|
|
|
|
|
if ([[dictForClass objectForKey: @"Super"] isEqual: superclass])
|
2002-07-21 04:04:18 +00:00
|
|
|
{
|
|
|
|
[subclasses addObject: object];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return subclasses;
|
|
|
|
}
|
|
|
|
|
2002-03-25 01:44:01 +00:00
|
|
|
- (NSArray *) subClassesOf: (NSString *)superclass
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSArray *allClasses = [_classInformation allKeys];
|
2002-03-25 01:44:01 +00:00
|
|
|
NSEnumerator *cen = [allClasses objectEnumerator];
|
|
|
|
id object = nil;
|
|
|
|
NSMutableArray *subclasses = [NSMutableArray array];
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
while ((object = [cen nextObject]))
|
2002-03-25 01:44:01 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *dictForClass = [_classInformation objectForKey: object];
|
2005-05-21 15:10:14 +00:00
|
|
|
NSString *superClassName = [dictForClass objectForKey: @"Super"];
|
|
|
|
if ([superClassName isEqual: superclass] ||
|
|
|
|
(superClassName == nil && superclass == nil))
|
2004-04-27 05:30:52 +00:00
|
|
|
{
|
2002-03-25 01:44:01 +00:00
|
|
|
[subclasses addObject: object];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-28 02:31:06 +00:00
|
|
|
return [subclasses sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)];
|
2002-03-25 01:44:01 +00:00
|
|
|
}
|
|
|
|
|
2002-07-15 05:58:01 +00:00
|
|
|
- (void) removeClassNamed: (NSString *)className
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
if ([_customClasses containsObject: className])
|
2002-07-15 05:58:01 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSEnumerator *en = [_customClassMap keyEnumerator];
|
2003-08-24 17:10:05 +00:00
|
|
|
id object = nil;
|
2004-07-12 04:16:09 +00:00
|
|
|
id owner = nil;
|
2003-08-24 17:10:05 +00:00
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
[_customClasses removeObject: className];
|
2003-08-24 17:10:05 +00:00
|
|
|
|
|
|
|
while((object = [en nextObject]) != nil)
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
id customClassName = [_customClassMap objectForKey: object];
|
2003-08-24 17:10:05 +00:00
|
|
|
if(customClassName != nil)
|
|
|
|
{
|
|
|
|
if([className isEqualToString: customClassName])
|
|
|
|
{
|
|
|
|
NSDebugLog(@"Deleting object -> customClass association %@ -> %@",object,customClassName);
|
2023-07-08 17:30:13 +00:00
|
|
|
[_customClassMap removeObjectForKey: object];
|
2003-08-24 17:10:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-07-12 04:16:09 +00:00
|
|
|
|
|
|
|
// get the owner and reset the class name to NSApplication.
|
2023-07-08 17:30:13 +00:00
|
|
|
owner = [_document objectForName: @"NSOwner"];
|
2004-07-12 04:16:09 +00:00
|
|
|
if([className isEqual: [owner className]])
|
|
|
|
{
|
|
|
|
[owner setClassName: @"NSApplication"];
|
|
|
|
}
|
2002-07-15 05:58:01 +00:00
|
|
|
}
|
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
[_classInformation removeObjectForKey: className];
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2003-06-30 02:15:00 +00:00
|
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
postNotificationName: GormDidDeleteClassNotification
|
|
|
|
object: self];
|
2002-07-15 05:58:01 +00:00
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (BOOL) renameClassNamed: (NSString *)oldName newName: (NSString *)newName
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
id classInfo = [_classInformation objectForKey: oldName];
|
2003-06-30 02:15:00 +00:00
|
|
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
2003-08-24 17:10:05 +00:00
|
|
|
NSString *name = [newName copy];
|
|
|
|
|
|
|
|
NSDebugLog(@"Old name %@, new name %@",oldName,name);
|
2001-05-08 09:43:11 +00:00
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
if (classInfo != nil && [_classInformation objectForKey: name] == nil)
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
2012-04-20 06:12:32 +00:00
|
|
|
NSUInteger index = 0;
|
2004-04-03 18:21:54 +00:00
|
|
|
NSArray *subclasses = [self subClassesOf: oldName];
|
2002-07-14 23:54:05 +00:00
|
|
|
|
2004-05-29 01:40:14 +00:00
|
|
|
RETAIN(classInfo); // prevent loss of the information...
|
2023-07-08 17:30:13 +00:00
|
|
|
[_classInformation removeObjectForKey: oldName];
|
|
|
|
[_classInformation setObject: classInfo forKey: name];
|
2004-05-29 01:40:14 +00:00
|
|
|
RELEASE(classInfo); // release our hold on it.
|
2001-05-08 09:43:11 +00:00
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
if ((index = [_customClasses indexOfObject: oldName]) != NSNotFound)
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSEnumerator *en = [_customClassMap keyEnumerator];
|
2004-04-03 18:21:54 +00:00
|
|
|
NSEnumerator *cen = [subclasses objectEnumerator];
|
|
|
|
id sc = nil;
|
2003-08-24 17:10:05 +00:00
|
|
|
id object = nil;
|
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDebugLog(@"replacing object with %@, %@",name, _customClasses);
|
|
|
|
[_customClasses replaceObjectAtIndex: index withObject: name];
|
|
|
|
NSDebugLog(@"replaced object with %@, %@",name, _customClasses);
|
2003-08-24 17:10:05 +00:00
|
|
|
|
|
|
|
// show the class map before...
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDebugLog(@"_customClassMap = %@",_customClassMap);
|
2003-08-24 17:10:05 +00:00
|
|
|
while((object = [en nextObject]) != nil)
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
id customClassName = [_customClassMap objectForKey: object];
|
2003-08-24 17:10:05 +00:00
|
|
|
if(customClassName != nil)
|
|
|
|
{
|
|
|
|
if([oldName isEqualToString: customClassName])
|
|
|
|
{
|
|
|
|
NSDebugLog(@"Replacing object -> customClass association %@ -> %@",object,customClassName);
|
2023-07-08 17:30:13 +00:00
|
|
|
[_customClassMap setObject: name forKey: object];
|
2003-08-24 17:10:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDebugLog(@"New _customClassMap = %@",_customClassMap); // and after
|
2004-04-03 18:21:54 +00:00
|
|
|
|
|
|
|
// Iterate over the list of subclasses and replace their referece with the new
|
|
|
|
// name.
|
|
|
|
while((sc = [cen nextObject]) != nil)
|
|
|
|
{
|
|
|
|
[self setSuperClassNamed: name
|
|
|
|
forClassNamed: sc];
|
|
|
|
}
|
2004-05-14 06:32:24 +00:00
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
[self touch];
|
2002-07-14 23:54:05 +00:00
|
|
|
}
|
2003-08-24 17:10:05 +00:00
|
|
|
else
|
|
|
|
NSLog(@"customClass not found %@",oldName);
|
2002-07-14 23:54:05 +00:00
|
|
|
|
2003-06-30 02:15:00 +00:00
|
|
|
[nc postNotificationName: IBClassNameChangedNotification object: self];
|
2001-05-08 09:43:11 +00:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
else return NO;
|
|
|
|
}
|
2003-02-13 13:32:59 +00:00
|
|
|
|
2004-02-12 06:56:56 +00:00
|
|
|
- (NSString *)parentOfClass: (NSString *)aClass
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *dictForClass = [_classInformation objectForKey: aClass];
|
2004-02-12 06:56:56 +00:00
|
|
|
return [dictForClass objectForKey: @"Super"];
|
|
|
|
}
|
|
|
|
|
2006-06-05 05:48:10 +00:00
|
|
|
- (NSData *) nibData
|
|
|
|
{
|
|
|
|
NSMutableDictionary *dict = nil;
|
|
|
|
NSMutableArray *classes = nil;
|
|
|
|
NSEnumerator *enumerator = nil;
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableArray *cats = [NSMutableArray arrayWithArray: _categoryClasses];
|
2006-06-05 05:48:10 +00:00
|
|
|
id name = nil;
|
2006-08-01 04:16:34 +00:00
|
|
|
|
2006-06-05 05:48:10 +00:00
|
|
|
// save all custom classes....
|
|
|
|
dict = [NSMutableDictionary dictionary];
|
|
|
|
[dict setObject: @"1" forKey: @"IBVersion"];
|
|
|
|
classes = [NSMutableArray array];
|
|
|
|
|
|
|
|
// build IBClasses...
|
2023-07-08 17:30:13 +00:00
|
|
|
enumerator = [_customClasses objectEnumerator];
|
2006-06-05 05:48:10 +00:00
|
|
|
while ((name = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSDictionary *classInfo;
|
|
|
|
NSMutableDictionary *newInfo;
|
|
|
|
id obj;
|
|
|
|
id extraObj;
|
|
|
|
|
|
|
|
// get the info...
|
2023-07-08 17:30:13 +00:00
|
|
|
classInfo = [_classInformation objectForKey: name];
|
2006-06-05 05:48:10 +00:00
|
|
|
|
|
|
|
newInfo = [[NSMutableDictionary alloc] init];
|
|
|
|
[newInfo setObject: name forKey: @"CLASS"];
|
|
|
|
|
|
|
|
// superclass...
|
|
|
|
obj = [classInfo objectForKey: @"Super"];
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
[newInfo setObject: obj forKey: @"SUPERCLASS"];
|
|
|
|
}
|
|
|
|
|
|
|
|
// outlets...
|
|
|
|
obj = [classInfo objectForKey: @"Outlets"];
|
|
|
|
extraObj = [classInfo objectForKey: @"ExtraOutlets"];
|
|
|
|
if (obj && extraObj)
|
|
|
|
{
|
|
|
|
obj = [obj arrayByAddingObjectsFromArray: extraObj];
|
|
|
|
}
|
|
|
|
else if (extraObj)
|
|
|
|
{
|
|
|
|
obj = extraObj;
|
|
|
|
}
|
2006-08-01 04:16:34 +00:00
|
|
|
if (obj != nil && [obj count] > 0)
|
2006-06-05 05:48:10 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *outletDict = [NSMutableDictionary dictionary];
|
|
|
|
NSEnumerator *oen = [obj objectEnumerator];
|
|
|
|
id outlet = nil;
|
|
|
|
|
|
|
|
while((outlet = [oen nextObject]) != nil)
|
|
|
|
{
|
|
|
|
[outletDict setObject: @"id" forKey: outlet];
|
|
|
|
}
|
|
|
|
|
|
|
|
[newInfo setObject: outletDict forKey: @"OUTLETS"];
|
|
|
|
}
|
|
|
|
|
|
|
|
// actions...
|
|
|
|
obj = [classInfo objectForKey: @"Actions"];
|
|
|
|
extraObj = [classInfo objectForKey: @"ExtraActions"];
|
|
|
|
if (obj && extraObj)
|
|
|
|
{
|
|
|
|
obj = [obj arrayByAddingObjectsFromArray: extraObj];
|
|
|
|
}
|
|
|
|
else if (extraObj)
|
|
|
|
{
|
|
|
|
obj = extraObj;
|
|
|
|
}
|
2006-08-01 04:16:34 +00:00
|
|
|
if (obj != nil && [obj count] > 0)
|
2006-06-05 05:48:10 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *actionDict = [NSMutableDictionary dictionary];
|
|
|
|
NSEnumerator *aen = [obj objectEnumerator];
|
|
|
|
id action = nil;
|
|
|
|
|
|
|
|
while((action = [aen nextObject]) != nil)
|
|
|
|
{
|
2006-08-01 04:16:34 +00:00
|
|
|
NSString *actionName = nil;
|
|
|
|
NSScanner *scanner = [NSScanner scannerWithString: action];
|
|
|
|
|
2009-01-06 14:14:48 +00:00
|
|
|
if ([scanner scanUpToString: @":" intoString: &actionName])
|
|
|
|
[actionDict setObject: @"id" forKey: actionName];
|
2006-06-05 05:48:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[newInfo setObject: actionDict forKey: @"ACTIONS"];
|
|
|
|
}
|
2006-08-01 04:16:34 +00:00
|
|
|
|
|
|
|
[newInfo setObject: @"ObjC" forKey: @"LANGUAGE"];
|
2006-06-05 05:48:10 +00:00
|
|
|
|
|
|
|
[classes addObject: newInfo];
|
|
|
|
}
|
|
|
|
|
2006-08-01 04:16:34 +00:00
|
|
|
// Save all categories on existing, non-custom classes....
|
|
|
|
// Always save the FirstResponder....
|
|
|
|
if([cats containsObject: @"FirstResponder"] == NO)
|
|
|
|
{
|
|
|
|
[cats addObject: @"FirstResponder"];
|
|
|
|
}
|
|
|
|
enumerator = [cats objectEnumerator];
|
2006-06-05 05:48:10 +00:00
|
|
|
while((name = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSDictionary *classInfo;
|
|
|
|
NSMutableDictionary *newInfo;
|
|
|
|
id obj;
|
|
|
|
|
|
|
|
// get the info...
|
2023-07-08 17:30:13 +00:00
|
|
|
classInfo = [_classInformation objectForKey: name];
|
2006-06-05 05:48:10 +00:00
|
|
|
newInfo = [NSMutableDictionary dictionary];
|
|
|
|
[newInfo setObject: name forKey: @"CLASS"];
|
|
|
|
|
|
|
|
// superclass...
|
|
|
|
obj = [classInfo objectForKey: @"Super"];
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
[newInfo setObject: obj forKey: @"SUPERCLASS"];
|
|
|
|
}
|
|
|
|
|
|
|
|
// actions...
|
|
|
|
obj = [classInfo objectForKey: @"ExtraActions"];
|
2006-08-01 04:16:34 +00:00
|
|
|
if (obj != nil && [obj count] > 0)
|
2006-06-05 05:48:10 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *actionDict = [NSMutableDictionary dictionary];
|
|
|
|
NSEnumerator *aen = [obj objectEnumerator];
|
|
|
|
id action = nil;
|
|
|
|
|
|
|
|
while((action = [aen nextObject]) != nil)
|
|
|
|
{
|
2006-08-01 04:16:34 +00:00
|
|
|
NSString *actionName = nil;
|
|
|
|
NSScanner *scanner = [NSScanner scannerWithString: action];
|
|
|
|
|
2009-01-06 14:14:48 +00:00
|
|
|
if ([scanner scanUpToString: @":" intoString: &actionName])
|
|
|
|
[actionDict setObject: @"id" forKey: actionName];
|
2006-06-05 05:48:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[newInfo setObject: actionDict forKey: @"ACTIONS"];
|
|
|
|
}
|
|
|
|
|
2006-08-05 12:48:45 +00:00
|
|
|
[newInfo setObject: @"ObjC" forKey: @"LANGUAGE"];
|
|
|
|
|
2006-06-05 05:48:10 +00:00
|
|
|
[classes addObject: newInfo];
|
|
|
|
}
|
|
|
|
|
2006-08-01 04:16:34 +00:00
|
|
|
[dict setObject: classes forKey: @"IBClasses"];
|
2006-06-05 05:48:10 +00:00
|
|
|
|
2006-08-01 04:16:34 +00:00
|
|
|
return [NSPropertyListSerialization dataFromPropertyList: dict
|
|
|
|
format: NSPropertyListOpenStepFormat
|
|
|
|
errorDescription: NULL];
|
2006-06-05 05:48:10 +00:00
|
|
|
}
|
|
|
|
|
2006-06-05 02:12:00 +00:00
|
|
|
- (NSData *) data
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
2006-06-05 02:12:00 +00:00
|
|
|
NSMutableDictionary *ci = nil;
|
|
|
|
NSEnumerator *enumerator = nil;
|
|
|
|
id key = nil;
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
// save all custom classes....
|
2006-06-05 05:48:10 +00:00
|
|
|
ci = [NSMutableDictionary dictionary];
|
2023-07-08 17:30:13 +00:00
|
|
|
enumerator = [_customClasses objectEnumerator];
|
2001-05-08 09:43:11 +00:00
|
|
|
while ((key = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSDictionary *classInfo;
|
|
|
|
NSMutableDictionary *newInfo;
|
|
|
|
id obj;
|
|
|
|
id extraObj;
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
// get the info...
|
2023-07-08 17:30:13 +00:00
|
|
|
classInfo = [_classInformation objectForKey: key];
|
2005-06-17 04:41:24 +00:00
|
|
|
newInfo = [[NSMutableDictionary alloc] init];
|
2001-05-08 09:43:11 +00:00
|
|
|
[ci setObject: newInfo forKey: key];
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
// superclass...
|
2001-05-08 09:43:11 +00:00
|
|
|
obj = [classInfo objectForKey: @"Super"];
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
[newInfo setObject: obj forKey: @"Super"];
|
|
|
|
}
|
2004-11-04 06:46:26 +00:00
|
|
|
|
|
|
|
// outlets...
|
2001-05-08 09:43:11 +00:00
|
|
|
obj = [classInfo objectForKey: @"Outlets"];
|
|
|
|
extraObj = [classInfo objectForKey: @"ExtraOutlets"];
|
2001-07-09 15:39:20 +00:00
|
|
|
if (obj && extraObj)
|
|
|
|
{
|
|
|
|
obj = [obj arrayByAddingObjectsFromArray: extraObj];
|
|
|
|
}
|
|
|
|
else if (extraObj)
|
|
|
|
{
|
|
|
|
obj = extraObj;
|
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
[newInfo setObject: obj forKey: @"Outlets"];
|
|
|
|
}
|
2004-11-04 06:46:26 +00:00
|
|
|
|
|
|
|
// actions...
|
2001-05-08 09:43:11 +00:00
|
|
|
obj = [classInfo objectForKey: @"Actions"];
|
|
|
|
extraObj = [classInfo objectForKey: @"ExtraActions"];
|
2001-07-09 15:39:20 +00:00
|
|
|
if (obj && extraObj)
|
|
|
|
{
|
|
|
|
obj = [obj arrayByAddingObjectsFromArray: extraObj];
|
|
|
|
}
|
|
|
|
else if (extraObj)
|
|
|
|
{
|
|
|
|
obj = extraObj;
|
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
[newInfo setObject: obj forKey: @"Actions"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
// save all categories on existing, non-custom classes....
|
2023-07-08 17:30:13 +00:00
|
|
|
enumerator = [_categoryClasses objectEnumerator];
|
2004-11-07 19:32:57 +00:00
|
|
|
while((key = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSDictionary *classInfo;
|
|
|
|
NSMutableDictionary *newInfo;
|
|
|
|
id obj;
|
|
|
|
|
|
|
|
// get the info...
|
2023-07-08 17:30:13 +00:00
|
|
|
classInfo = [_classInformation objectForKey: key];
|
2006-06-05 05:48:10 +00:00
|
|
|
newInfo = [NSMutableDictionary dictionary];
|
2004-11-07 19:32:57 +00:00
|
|
|
[ci setObject: newInfo forKey: key];
|
|
|
|
|
|
|
|
// superclass...
|
|
|
|
obj = [classInfo objectForKey: @"Super"];
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
[newInfo setObject: obj forKey: @"Super"];
|
|
|
|
}
|
|
|
|
|
|
|
|
// actions...
|
|
|
|
obj = [classInfo objectForKey: @"ExtraActions"];
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
[newInfo setObject: obj forKey: @"Actions"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-09 13:52:27 +00:00
|
|
|
// add the extras...
|
2004-11-08 03:58:41 +00:00
|
|
|
[ci setObject: @"Do NOT change this file, Gorm maintains it"
|
2004-11-08 04:18:49 +00:00
|
|
|
forKey: @"## Comment"];
|
2004-11-08 03:58:41 +00:00
|
|
|
|
2006-08-01 04:16:34 +00:00
|
|
|
return [NSPropertyListSerialization dataFromPropertyList: ci
|
|
|
|
format: NSPropertyListOpenStepFormat
|
|
|
|
errorDescription: NULL];
|
2006-06-05 02:12:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) saveToFile: (NSString *)path
|
|
|
|
{
|
2006-06-15 04:51:33 +00:00
|
|
|
return [[self data] writeToFile: path atomically: YES];
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (BOOL) loadFromFile: (NSString *)path
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
2004-11-09 13:52:27 +00:00
|
|
|
NSDictionary *dict;
|
2001-05-08 09:43:11 +00:00
|
|
|
NSEnumerator *enumerator;
|
|
|
|
NSString *key;
|
|
|
|
|
2002-12-15 18:17:53 +00:00
|
|
|
NSDebugLog(@"Load from file %@",path);
|
2001-05-08 09:43:11 +00:00
|
|
|
|
|
|
|
dict = [NSDictionary dictionaryWithContentsOfFile: path];
|
|
|
|
if (dict == nil)
|
|
|
|
{
|
|
|
|
NSLog(@"Could not load classes dictionary");
|
|
|
|
return NO;
|
|
|
|
}
|
2004-11-04 06:46:26 +00:00
|
|
|
|
2001-05-08 09:43:11 +00:00
|
|
|
/*
|
|
|
|
* Convert property-list data into a mutable structure.
|
|
|
|
*/
|
2023-07-08 17:30:13 +00:00
|
|
|
ASSIGN(_classInformation, [[NSMutableDictionary alloc] init]);
|
2004-11-09 13:52:27 +00:00
|
|
|
|
|
|
|
// iterate over all entries..
|
2001-05-08 09:43:11 +00:00
|
|
|
enumerator = [dict keyEnumerator];
|
|
|
|
while ((key = [enumerator nextObject]) != nil)
|
|
|
|
{
|
2004-11-04 06:46:26 +00:00
|
|
|
NSDictionary *classInfo = [dict objectForKey: key];
|
|
|
|
NSMutableDictionary *newInfo;
|
|
|
|
id obj;
|
|
|
|
|
2005-06-17 04:41:24 +00:00
|
|
|
newInfo = [[NSMutableDictionary alloc] init];
|
2004-11-04 06:46:26 +00:00
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
[_classInformation setObject: newInfo forKey: key];
|
2002-10-31 15:00:17 +00:00
|
|
|
|
2004-11-04 06:46:26 +00:00
|
|
|
// superclass
|
2001-05-08 09:43:11 +00:00
|
|
|
obj = [classInfo objectForKey: @"Super"];
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
[newInfo setObject: obj forKey: @"Super"];
|
|
|
|
}
|
2002-10-31 15:00:17 +00:00
|
|
|
|
|
|
|
// outlets
|
2001-05-08 09:43:11 +00:00
|
|
|
obj = [classInfo objectForKey: @"Outlets"];
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
obj = [obj mutableCopy];
|
|
|
|
[obj sortUsingSelector: @selector(compare:)];
|
|
|
|
[newInfo setObject: obj forKey: @"Outlets"];
|
2004-11-04 06:46:26 +00:00
|
|
|
RELEASE(obj);
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
2004-11-04 06:46:26 +00:00
|
|
|
|
2002-10-31 15:00:17 +00:00
|
|
|
// actions
|
2001-05-08 09:43:11 +00:00
|
|
|
obj = [classInfo objectForKey: @"Actions"];
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
obj = [obj mutableCopy];
|
|
|
|
[obj sortUsingSelector: @selector(compare:)];
|
|
|
|
[newInfo setObject: obj forKey: @"Actions"];
|
2004-11-04 06:46:26 +00:00
|
|
|
RELEASE(obj);
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2006-06-05 05:48:10 +00:00
|
|
|
- (BOOL) loadNibFormatCustomClassesWithDict: (NSDictionary *)dict
|
|
|
|
{
|
|
|
|
NSArray *classes = [dict objectForKey: @"IBClasses"];
|
|
|
|
NSEnumerator *en = [classes objectEnumerator];
|
|
|
|
BOOL result = NO;
|
|
|
|
id cls = nil;
|
|
|
|
|
2009-08-08 07:18:33 +00:00
|
|
|
// If there are no classes to add, return gracefully.
|
|
|
|
if([classes count] == 0)
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2006-06-05 05:48:10 +00:00
|
|
|
while((cls = [en nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSString *className = [cls objectForKey: @"CLASS"];
|
|
|
|
NSString *superClass = [cls objectForKey: @"SUPERCLASS"];
|
|
|
|
NSDictionary *actionDict = [cls objectForKey: @"ACTIONS"];
|
|
|
|
NSDictionary *outletDict = [cls objectForKey: @"OUTLETS"];
|
|
|
|
NSMutableArray *actions = [NSMutableArray array];
|
|
|
|
NSArray *outlets = [outletDict allKeys];
|
|
|
|
NSEnumerator *aen = [actionDict keyEnumerator];
|
|
|
|
id action = nil;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Convert action format.
|
|
|
|
//
|
|
|
|
while((action = [aen nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSString *aname = [action stringByAppendingString: @":"];
|
|
|
|
[actions addObject: aname];
|
|
|
|
}
|
2006-06-05 02:12:00 +00:00
|
|
|
|
2006-06-05 05:48:10 +00:00
|
|
|
//
|
|
|
|
// If the class is known, add the actions/outlets, if it's
|
|
|
|
// not, then add all of the information.
|
|
|
|
//
|
|
|
|
if([self isKnownClass: className])
|
|
|
|
{
|
|
|
|
[self addActions: actions forClassNamed: className];
|
|
|
|
[self addOutlets: outlets forClassNamed: className];
|
|
|
|
result = YES;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = [self addClassNamed: className
|
|
|
|
withSuperClassNamed: superClass
|
|
|
|
withActions: actions
|
|
|
|
withOutlets: outlets];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) loadNibFormatCustomClassesWithData: (NSData *)data
|
|
|
|
{
|
|
|
|
NSString *dictString = AUTORELEASE([[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding]);
|
|
|
|
NSDictionary *dict = [dictString propertyList];
|
2006-06-14 05:47:54 +00:00
|
|
|
return [self loadNibFormatCustomClassesWithDict: dict];
|
2006-06-05 05:48:10 +00:00
|
|
|
}
|
2006-06-05 02:12:00 +00:00
|
|
|
|
2002-07-14 23:54:05 +00:00
|
|
|
// this method will load the custom classes and merge them with the
|
|
|
|
// Class information loaded at initialization time.
|
2003-02-13 13:32:59 +00:00
|
|
|
- (BOOL) loadCustomClasses: (NSString *)path
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
2006-06-05 05:48:10 +00:00
|
|
|
NSMutableDictionary *dict;
|
|
|
|
BOOL result = NO;
|
2002-07-14 23:54:05 +00:00
|
|
|
|
2002-12-15 18:17:53 +00:00
|
|
|
NSDebugLog(@"Load custom classes from file %@",path);
|
2002-07-14 23:54:05 +00:00
|
|
|
|
|
|
|
dict = [NSMutableDictionary dictionaryWithContentsOfFile: path];
|
|
|
|
if (dict == nil)
|
|
|
|
{
|
|
|
|
NSLog(@"Could not load custom classes dictionary");
|
|
|
|
return NO;
|
|
|
|
}
|
2004-11-08 03:58:41 +00:00
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
if (_classInformation == nil)
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
|
|
|
NSLog(@"Default classes file not loaded");
|
|
|
|
return NO;
|
|
|
|
}
|
2006-06-05 02:12:00 +00:00
|
|
|
|
2006-06-05 05:48:10 +00:00
|
|
|
if([path isEqualToString: @"data.classes"])
|
|
|
|
{
|
|
|
|
result = [self loadCustomClassesWithDict: dict];
|
|
|
|
}
|
|
|
|
else if([path isEqualToString: @"classes.nib"])
|
|
|
|
{
|
|
|
|
result = [self loadNibFormatCustomClassesWithDict: dict];
|
|
|
|
}
|
|
|
|
return result;
|
2006-06-05 02:12:00 +00:00
|
|
|
}
|
2002-07-14 23:54:05 +00:00
|
|
|
|
2006-06-05 02:12:00 +00:00
|
|
|
- (BOOL) loadCustomClassesWithData: (NSData *)data
|
|
|
|
{
|
2006-06-05 05:48:10 +00:00
|
|
|
NSString *dictString = AUTORELEASE([[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding]);
|
2006-06-05 02:12:00 +00:00
|
|
|
NSDictionary *dict = [dictString propertyList];
|
|
|
|
return [self loadCustomClassesWithDict: dict];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) loadCustomClassesWithDict: (NSDictionary *)dict
|
|
|
|
{
|
|
|
|
NSEnumerator *en = nil;
|
|
|
|
id key = nil;
|
2004-11-09 13:52:27 +00:00
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
// Iterate over the set of classes, if it's in the _classInformation
|
2004-11-07 19:32:57 +00:00
|
|
|
// list, it's a category, if it's not it's a custom class.
|
2004-11-08 05:20:05 +00:00
|
|
|
en = [dict keyEnumerator];
|
2004-11-07 19:32:57 +00:00
|
|
|
while((key = [en nextObject]) != nil)
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
2004-11-08 04:08:36 +00:00
|
|
|
id class_dict = [dict objectForKey: key];
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2004-11-08 04:08:36 +00:00
|
|
|
// Class information is always a dictionary, other information, such as
|
|
|
|
// comments or version numbers, will appear as strings.
|
|
|
|
if([class_dict isKindOfClass: [NSDictionary class]])
|
|
|
|
{
|
|
|
|
NSMutableDictionary *classDict = (NSMutableDictionary *)class_dict;
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: key];
|
2004-11-08 04:08:36 +00:00
|
|
|
if(info == nil)
|
2004-11-07 19:32:57 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
[_customClasses addObject: key];
|
|
|
|
[_classInformation setObject: classDict forKey: key];
|
2004-11-08 04:08:36 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSMutableArray *actions = [classDict objectForKey: @"Actions"];
|
2004-12-14 11:13:59 +00:00
|
|
|
NSMutableArray *origActions = [info objectForKey: @"Actions"];
|
|
|
|
NSMutableArray *allActions = nil;
|
2004-11-08 04:08:36 +00:00
|
|
|
|
|
|
|
// remove any duplicate actions...
|
2004-12-14 11:13:59 +00:00
|
|
|
if(origActions != nil)
|
2004-11-07 19:32:57 +00:00
|
|
|
{
|
2004-12-14 11:13:59 +00:00
|
|
|
allActions = [NSMutableArray arrayWithArray: origActions];
|
2005-01-09 06:40:05 +00:00
|
|
|
|
|
|
|
[actions removeObjectsInArray: origActions];
|
2004-12-14 11:13:59 +00:00
|
|
|
[allActions addObjectsFromArray: actions];
|
|
|
|
[info setObject: allActions forKey: @"AllActions"];
|
2004-11-07 19:32:57 +00:00
|
|
|
}
|
2004-11-08 04:08:36 +00:00
|
|
|
|
|
|
|
// if there are any action methods left after the process above,
|
|
|
|
// add it, otherwise don't.
|
|
|
|
if([actions count] > 0)
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
[_categoryClasses addObject: key];
|
2004-11-08 04:08:36 +00:00
|
|
|
[info setObject: actions forKey: @"ExtraActions"];
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-10-31 15:00:17 +00:00
|
|
|
|
2002-07-14 23:54:05 +00:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) isCustomClass: (NSString *)className
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
return ([_customClasses indexOfObject: className] != NSNotFound);
|
2004-11-04 06:46:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) isNonCustomClass: (NSString *)className
|
|
|
|
{
|
|
|
|
return !([self isCustomClass: className]);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) isCategoryForClass: (NSString *)className
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
return ([_categoryClasses indexOfObject: className] != NSNotFound);
|
2002-07-14 23:54:05 +00:00
|
|
|
}
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
- (BOOL) isAction: (NSString *)actionName onCategoryForClassNamed: (NSString *)className
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *info = [_classInformation objectForKey: className];
|
2004-11-07 19:32:57 +00:00
|
|
|
BOOL result = NO;
|
|
|
|
|
|
|
|
if([self isCategoryForClass: className])
|
|
|
|
{
|
|
|
|
if(info != nil)
|
|
|
|
{
|
|
|
|
NSArray *extra = [info objectForKey: @"ExtraActions"];
|
|
|
|
if(extra != nil)
|
|
|
|
{
|
|
|
|
result = [extra containsObject: actionName];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2002-11-21 01:00:08 +00:00
|
|
|
- (BOOL) isKnownClass: (NSString *)className
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
return ([_classInformation objectForKey: className] != nil);
|
2002-11-21 01:00:08 +00:00
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (BOOL) setSuperClassNamed: (NSString *)superclass
|
|
|
|
forClassNamed: (NSString *)subclass
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
|
|
|
NSArray *cn = [self allClassNames];
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
if (superclass != nil
|
|
|
|
&& subclass != nil
|
|
|
|
&& [cn containsObject: subclass]
|
2005-07-13 06:19:16 +00:00
|
|
|
&& ([cn containsObject: superclass] || [self isRootClass: superclass])
|
2004-11-07 19:32:57 +00:00
|
|
|
&& [self isSuperclass: subclass linkedToClass: superclass] == NO)
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *info;
|
|
|
|
|
2023-07-08 17:30:13 +00:00
|
|
|
info = [_classInformation objectForKey: subclass];
|
2001-05-08 09:43:11 +00:00
|
|
|
if (info != nil)
|
|
|
|
{
|
2004-12-11 23:05:52 +00:00
|
|
|
// remove actions/outlets inherited from superclasses...
|
|
|
|
[info removeObjectForKey: @"AllActions"];
|
|
|
|
[info removeObjectForKey: @"AllOutlets"];
|
|
|
|
|
|
|
|
// change the parent of the class...
|
2001-05-08 09:43:11 +00:00
|
|
|
[info setObject: superclass forKey: @"Super"];
|
2004-12-11 23:05:52 +00:00
|
|
|
|
|
|
|
// recalculate the actions/outlets...
|
|
|
|
[self allActionsForClassNamed: subclass];
|
|
|
|
[self allOutletsForClassNamed: subclass];
|
|
|
|
|
|
|
|
// return success.
|
2001-05-08 09:43:11 +00:00
|
|
|
return YES;
|
|
|
|
}
|
2001-07-09 15:39:20 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
|
|
|
return NO;
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSString *) superClassNameForClassNamed: (NSString *)className
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [_classInformation objectForKey: className];
|
2001-05-08 09:43:11 +00:00
|
|
|
NSString *superName = nil;
|
|
|
|
|
|
|
|
if (info != nil)
|
|
|
|
{
|
|
|
|
superName = [info objectForKey: @"Super"];
|
|
|
|
}
|
|
|
|
|
2004-11-07 19:32:57 +00:00
|
|
|
return superName;
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
2001-07-09 15:39:20 +00:00
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (BOOL) isSuperclass: (NSString *)superclass linkedToClass: (NSString *)subclass
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
|
|
|
NSString *ssclass;
|
|
|
|
|
|
|
|
if (superclass == nil || subclass == nil)
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
2001-05-08 09:43:11 +00:00
|
|
|
ssclass = [self superClassNameForClassNamed: subclass];
|
|
|
|
if ([superclass isEqualToString: ssclass])
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
2004-11-07 19:32:57 +00:00
|
|
|
|
|
|
|
return [self isSuperclass: superclass linkedToClass: ssclass];
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
2001-07-06 17:10:51 +00:00
|
|
|
|
2004-12-14 11:13:59 +00:00
|
|
|
- (NSDictionary *) dictionaryForClassNamed: (NSString *)className
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSMutableDictionary *info = [NSMutableDictionary dictionaryWithDictionary: [_classInformation objectForKey: className]];
|
2004-12-14 11:13:59 +00:00
|
|
|
|
|
|
|
if(info != nil)
|
|
|
|
{
|
|
|
|
[info removeObjectForKey: @"AllActions"];
|
|
|
|
[info removeObjectForKey: @"AllOutlets"];
|
|
|
|
}
|
|
|
|
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
2001-07-06 17:10:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* create .m & .h files for a class
|
|
|
|
*/
|
2004-12-14 11:13:59 +00:00
|
|
|
- (BOOL) makeSourceAndHeaderFilesForClass: (NSString *)className
|
|
|
|
withName: (NSString *)sourcePath
|
|
|
|
and: (NSString *)headerPath
|
2001-07-06 17:10:51 +00:00
|
|
|
{
|
2001-07-09 15:39:20 +00:00
|
|
|
NSMutableString *headerFile;
|
|
|
|
NSMutableString *sourceFile;
|
|
|
|
NSData *headerData;
|
|
|
|
NSData *sourceData;
|
2004-04-27 05:30:52 +00:00
|
|
|
NSMutableArray *outlets;
|
|
|
|
NSMutableArray *actions;
|
2001-07-09 15:39:20 +00:00
|
|
|
NSString *actionName;
|
|
|
|
int i;
|
|
|
|
int n;
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *classInfo = [_classInformation objectForKey: className];
|
2001-07-06 17:10:51 +00:00
|
|
|
|
|
|
|
headerFile = [NSMutableString stringWithCapacity: 200];
|
|
|
|
sourceFile = [NSMutableString stringWithCapacity: 200];
|
2004-04-27 05:30:52 +00:00
|
|
|
|
|
|
|
// add all outlets and actions for the current class to the list...
|
|
|
|
outlets = [[classInfo objectForKey: @"Outlets"] mutableCopy];
|
|
|
|
[outlets addObjectsFromArray: [classInfo objectForKey: @"ExtraOutlets"]];
|
|
|
|
actions = [[classInfo objectForKey: @"Actions"] mutableCopy];
|
|
|
|
[actions addObjectsFromArray: [classInfo objectForKey: @"ExtraActions"]];
|
2001-07-06 17:10:51 +00:00
|
|
|
|
2004-04-27 05:30:52 +00:00
|
|
|
// header file comments...
|
2020-04-21 05:07:14 +00:00
|
|
|
[headerFile appendString: @"/* All rights reserved */\n\n"];
|
|
|
|
[sourceFile appendString: @"/* All rights reserved */\n\n"];
|
2023-07-14 21:30:28 +00:00
|
|
|
[headerFile appendString: [NSString stringWithFormat: @"#ifndef %@_H_INCLUDE\n", className]];
|
|
|
|
[headerFile appendString: [NSString stringWithFormat: @"#define %@_H_INCLUDE\n\n", className]];
|
2021-04-28 23:03:27 +00:00
|
|
|
[headerFile appendString: @"#import <AppKit/AppKit.h>\n\n"];
|
2001-07-06 17:10:51 +00:00
|
|
|
if ([[headerPath stringByDeletingLastPathComponent]
|
2001-07-09 15:39:20 +00:00
|
|
|
isEqualToString: [sourcePath stringByDeletingLastPathComponent]])
|
2001-07-06 17:10:51 +00:00
|
|
|
{
|
2021-04-28 23:03:27 +00:00
|
|
|
[sourceFile appendFormat: @"#import \"%@\"\n\n",
|
2001-07-09 15:39:20 +00:00
|
|
|
[headerPath lastPathComponent]];
|
2001-07-06 17:10:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-04-28 23:03:27 +00:00
|
|
|
[sourceFile appendFormat: @"#import \"%@\"\n\n",
|
2001-07-09 15:39:20 +00:00
|
|
|
headerPath];
|
|
|
|
}
|
|
|
|
[headerFile appendFormat: @"@interface %@ : %@\n{\n", className,
|
2023-07-14 21:30:28 +00:00
|
|
|
[self superClassNameForClassNamed: className]];
|
2001-07-09 15:39:20 +00:00
|
|
|
[sourceFile appendFormat: @"@implementation %@\n\n", className];
|
2001-07-06 17:10:51 +00:00
|
|
|
|
|
|
|
n = [outlets count];
|
2001-07-09 15:39:20 +00:00
|
|
|
for (i = 0; i < n; i++)
|
2001-07-06 17:10:51 +00:00
|
|
|
{
|
2021-04-28 23:03:27 +00:00
|
|
|
[headerFile appendFormat: @" IBOutlet id %@;\n", [outlets objectAtIndex: i]];
|
2001-07-06 17:10:51 +00:00
|
|
|
}
|
2023-07-14 21:30:28 +00:00
|
|
|
[headerFile appendFormat: @"}\n\n"];
|
2001-07-06 17:10:51 +00:00
|
|
|
|
|
|
|
n = [actions count];
|
2001-07-09 15:39:20 +00:00
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
actionName = [actions objectAtIndex: i];
|
2021-04-28 23:03:27 +00:00
|
|
|
[headerFile appendFormat: @"- (IBAction) %@ (id)sender;\n", actionName];
|
2001-07-09 15:39:20 +00:00
|
|
|
[sourceFile appendFormat:
|
2021-04-28 23:03:27 +00:00
|
|
|
@"- (IBAction) %@ (id)sender\n"
|
2001-07-09 15:39:20 +00:00
|
|
|
@"{\n"
|
|
|
|
@"}\n"
|
|
|
|
@"\n"
|
|
|
|
, [actions objectAtIndex: i]];
|
2001-07-06 17:10:51 +00:00
|
|
|
}
|
2023-07-14 21:30:28 +00:00
|
|
|
[headerFile appendFormat: @"\n@end\n\n"];
|
|
|
|
[headerFile appendString: [NSString stringWithFormat: @"#endif // %@_H_INCLUDE\n", className]];
|
2001-07-06 17:10:51 +00:00
|
|
|
[sourceFile appendFormat: @"@end\n"];
|
|
|
|
|
|
|
|
headerData = [headerFile dataUsingEncoding:
|
2001-07-09 15:39:20 +00:00
|
|
|
[NSString defaultCStringEncoding]];
|
2001-07-06 17:10:51 +00:00
|
|
|
sourceData = [sourceFile dataUsingEncoding:
|
2001-07-09 15:39:20 +00:00
|
|
|
[NSString defaultCStringEncoding]];
|
2001-07-06 17:10:51 +00:00
|
|
|
|
|
|
|
[headerData writeToFile: headerPath atomically: NO];
|
2010-08-04 17:10:45 +00:00
|
|
|
|
|
|
|
[[NSDistributedNotificationCenter defaultCenter]
|
|
|
|
postNotificationName: @"GormCreateFileNotification"
|
|
|
|
object: headerPath];
|
|
|
|
|
2001-07-06 17:10:51 +00:00
|
|
|
[sourceData writeToFile: sourcePath atomically: NO];
|
|
|
|
|
2010-08-04 17:10:45 +00:00
|
|
|
[[NSDistributedNotificationCenter defaultCenter]
|
|
|
|
postNotificationName: @"GormCreateFileNotification"
|
|
|
|
object: sourcePath];
|
|
|
|
|
2001-07-06 17:10:51 +00:00
|
|
|
return YES;
|
|
|
|
}
|
2002-07-14 23:54:05 +00:00
|
|
|
|
2004-05-19 01:36:37 +00:00
|
|
|
- (BOOL) parseHeader: (NSString *)headerPath
|
|
|
|
{
|
2004-11-27 10:56:40 +00:00
|
|
|
OCHeaderParser *ochp = AUTORELEASE([[OCHeaderParser alloc] initWithContentsOfFile: headerPath]);
|
2004-08-14 00:53:20 +00:00
|
|
|
BOOL result = NO;
|
2023-07-04 20:00:18 +00:00
|
|
|
|
2004-11-27 10:56:40 +00:00
|
|
|
if(ochp != nil)
|
|
|
|
{
|
|
|
|
result = [ochp parse];
|
|
|
|
if(result)
|
|
|
|
{
|
|
|
|
NSArray *classes = [ochp classes];
|
|
|
|
NSEnumerator *en = [classes objectEnumerator];
|
|
|
|
OCClass *cls = nil;
|
|
|
|
|
|
|
|
while((cls = (OCClass *)[en nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSArray *methods = [cls methods];
|
|
|
|
NSArray *ivars = [cls ivars];
|
|
|
|
NSString *superClass = [cls superClassName];
|
|
|
|
NSString *className = [cls className];
|
|
|
|
NSEnumerator *ien = [ivars objectEnumerator];
|
|
|
|
NSEnumerator *men = [methods objectEnumerator];
|
|
|
|
OCMethod *method = nil;
|
|
|
|
OCIVar *ivar = nil;
|
|
|
|
NSMutableArray *actions = [NSMutableArray array];
|
|
|
|
NSMutableArray *outlets = [NSMutableArray array];
|
|
|
|
|
2004-11-27 22:38:53 +00:00
|
|
|
// skip it, if it's category... for now. TODO: make categories work...
|
2004-11-27 10:56:40 +00:00
|
|
|
while((method = (OCMethod *)[men nextObject]) != nil)
|
|
|
|
{
|
|
|
|
if([method isAction])
|
|
|
|
{
|
|
|
|
[actions addObject: [method name]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while((ivar = (OCIVar *)[ien nextObject]) != nil)
|
|
|
|
{
|
|
|
|
if([ivar isOutlet])
|
|
|
|
{
|
|
|
|
[outlets addObject: [ivar name]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-29 02:28:49 +00:00
|
|
|
if(([self isKnownClass: superClass] || superClass == nil) &&
|
|
|
|
[cls isCategory] == NO)
|
2004-11-27 22:38:53 +00:00
|
|
|
{
|
2005-02-01 04:30:17 +00:00
|
|
|
if([self isKnownClass: className])
|
|
|
|
{
|
2023-07-04 20:00:18 +00:00
|
|
|
id<GormAppDelegate> delegate = (id<GormAppDelegate>)[NSApp delegate];
|
2023-07-18 21:17:13 +00:00
|
|
|
BOOL result = [delegate shouldBreakConnectionsReparsingClass: className];
|
2023-07-03 13:12:28 +00:00
|
|
|
|
2023-07-18 21:17:13 +00:00
|
|
|
if (result == YES)
|
2005-02-01 04:30:17 +00:00
|
|
|
{
|
2006-10-20 03:13:04 +00:00
|
|
|
// get the owner and reset the class name to NSApplication.
|
2023-07-08 17:30:13 +00:00
|
|
|
GormFilesOwner *owner = [_document objectForName: @"NSOwner"];
|
2006-10-20 03:13:04 +00:00
|
|
|
NSString *ownerClassName = [owner className];
|
|
|
|
|
2010-05-06 00:54:29 +00:00
|
|
|
// Retain this, in case we're dealing with the NSOwner...
|
|
|
|
RETAIN(ownerClassName);
|
|
|
|
|
2005-02-01 04:30:17 +00:00
|
|
|
// delete the class..
|
|
|
|
[self removeClassNamed: className];
|
|
|
|
|
|
|
|
// re-add it.
|
|
|
|
[self addClassNamed: className
|
|
|
|
withSuperClassNamed: superClass
|
|
|
|
withActions: actions
|
|
|
|
withOutlets: outlets];
|
2006-10-20 02:59:11 +00:00
|
|
|
|
2010-05-06 00:54:29 +00:00
|
|
|
// Set the owner back to the class name, if needed.
|
|
|
|
if([className isEqualToString: ownerClassName])
|
|
|
|
{
|
|
|
|
[owner setClassName: className];
|
|
|
|
}
|
|
|
|
|
2006-10-20 02:59:11 +00:00
|
|
|
// refresh the connections.
|
2023-07-08 17:30:13 +00:00
|
|
|
[_document refreshConnectionsForClassNamed: className];
|
2010-05-06 00:54:29 +00:00
|
|
|
|
|
|
|
// Release the owner classname...
|
|
|
|
RELEASE(ownerClassName);
|
2005-02-01 04:30:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[self addClassNamed: className
|
|
|
|
withSuperClassNamed: superClass
|
|
|
|
withActions: actions
|
|
|
|
withOutlets: outlets];
|
|
|
|
}
|
2004-11-27 22:38:53 +00:00
|
|
|
}
|
2005-02-15 04:29:32 +00:00
|
|
|
else if([cls isCategory] && [self isKnownClass: className])
|
|
|
|
{
|
|
|
|
[self addActions: actions forClassNamed: className];
|
|
|
|
}
|
2006-09-29 02:28:49 +00:00
|
|
|
else if(superClass != nil && [self isKnownClass: superClass] == NO)
|
2004-11-27 22:38:53 +00:00
|
|
|
{
|
|
|
|
result = NO;
|
2004-12-02 11:30:32 +00:00
|
|
|
[NSException raise: NSGenericException
|
2004-11-27 22:38:53 +00:00
|
|
|
format: @"The superclass %@ of class %@ is not known, please parse it.",
|
|
|
|
superClass, className];
|
|
|
|
}
|
2004-11-27 10:56:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-08-14 00:53:20 +00:00
|
|
|
|
|
|
|
return result;
|
2004-05-19 01:36:37 +00:00
|
|
|
}
|
|
|
|
|
2002-07-14 23:54:05 +00:00
|
|
|
- (BOOL) isAction: (NSString *)name ofClass: (NSString *)className
|
|
|
|
{
|
|
|
|
BOOL result = NO;
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *classInfo = [_classInformation objectForKey: className];
|
2002-07-14 23:54:05 +00:00
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
if (classInfo != nil)
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
|
|
|
NSArray *array = [classInfo objectForKey: @"Actions"];
|
|
|
|
NSArray *extra_array = [classInfo objectForKey: @"ExtraActions"];
|
|
|
|
NSMutableArray *combined = [NSMutableArray array];
|
|
|
|
|
|
|
|
[combined addObjectsFromArray: array];
|
|
|
|
[combined addObjectsFromArray: extra_array];
|
|
|
|
result = ([combined indexOfObject: name] != NSNotFound);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) isOutlet: (NSString *)name ofClass: (NSString *)className
|
|
|
|
{
|
|
|
|
BOOL result = NO;
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *classInfo = [_classInformation objectForKey: className];
|
2002-07-14 23:54:05 +00:00
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
if (classInfo != nil)
|
2002-07-14 23:54:05 +00:00
|
|
|
{
|
|
|
|
NSArray *array = [classInfo objectForKey: @"Outlets"];
|
|
|
|
NSArray *extra_array = [classInfo objectForKey: @"ExtraOutlets"];
|
|
|
|
NSMutableArray *combined = [NSMutableArray array];
|
|
|
|
|
|
|
|
[combined addObjectsFromArray: array];
|
|
|
|
[combined addObjectsFromArray: extra_array];
|
|
|
|
result = ([combined indexOfObject: name] != NSNotFound);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
1999-12-21 11:38:49 +00:00
|
|
|
|
2002-10-13 06:04:05 +00:00
|
|
|
// custom class support...
|
2003-01-14 06:29:34 +00:00
|
|
|
- (NSString *) customClassForName: (NSString *)name
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSString *result = [_customClassMap objectForKey: name];
|
2003-01-14 06:29:34 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2002-10-13 06:04:05 +00:00
|
|
|
- (NSString *) customClassForObject: (id)object
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSString *name = [_document nameForObject: object];
|
2003-01-14 06:29:34 +00:00
|
|
|
NSString *result = [self customClassForName: name];
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDebugLog(@"in customClassForObject: object = %@, name = %@, result = %@, _customClassMap = %@",
|
|
|
|
object, name, result, _customClassMap);
|
2003-01-08 05:54:20 +00:00
|
|
|
return result;
|
1999-12-21 11:38:49 +00:00
|
|
|
}
|
2001-05-08 09:43:11 +00:00
|
|
|
|
2004-12-16 10:38:14 +00:00
|
|
|
- (NSString *) classNameForObject: (id)object
|
|
|
|
{
|
|
|
|
NSString *className = [self customClassForObject: object];
|
|
|
|
if(className == nil)
|
|
|
|
{
|
|
|
|
className = [object className];
|
|
|
|
}
|
|
|
|
return className;
|
|
|
|
}
|
|
|
|
|
2002-10-13 06:04:05 +00:00
|
|
|
- (void) setCustomClass: (NSString *)className
|
2006-06-14 05:47:54 +00:00
|
|
|
forName: (NSString *)name
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
[_customClassMap setObject: className forKey: name];
|
1999-12-21 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2006-06-14 05:47:54 +00:00
|
|
|
- (void) removeCustomClassForName: (NSString *)name
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
[_customClassMap removeObjectForKey: name];
|
1999-12-21 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
- (NSMutableDictionary *) customClassMap
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
return _customClassMap;
|
1999-12-21 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
- (void) setCustomClassMap: (NSMutableDictionary *)dict
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
2002-10-13 06:04:05 +00:00
|
|
|
// copy the dictionary..
|
2002-12-15 18:17:53 +00:00
|
|
|
NSDebugLog(@"dictionary = %@",dict);
|
2023-07-08 17:30:13 +00:00
|
|
|
ASSIGN(_customClassMap, [dict mutableCopy]);
|
|
|
|
RETAIN(_customClassMap); // released in dealloc
|
1999-12-21 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
- (BOOL) isCustomClassMapEmpty
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
return ([_customClassMap count] == 0);
|
2001-05-08 09:43:11 +00:00
|
|
|
}
|
|
|
|
|
2005-07-13 06:19:16 +00:00
|
|
|
- (BOOL) isRootClass: (NSString *)className
|
|
|
|
{
|
|
|
|
return ([self superClassNameForClassNamed: className] == nil);
|
|
|
|
}
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
- (NSString *) nonCustomSuperClassOf: (NSString *)className
|
2001-05-08 09:43:11 +00:00
|
|
|
{
|
2002-10-13 06:04:05 +00:00
|
|
|
NSString *result = className;
|
2003-08-24 17:10:05 +00:00
|
|
|
|
2005-07-13 06:19:16 +00:00
|
|
|
if(![self isCustomClass: className] && ![self isRootClass: className])
|
1999-12-21 11:38:49 +00:00
|
|
|
{
|
2002-10-13 06:04:05 +00:00
|
|
|
result = [self superClassNameForClassNamed: result];
|
1999-12-21 11:38:49 +00:00
|
|
|
}
|
2003-09-09 02:57:30 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// iterate up the chain until a non-custom superclass is found...
|
|
|
|
while ([self isCustomClass: result])
|
|
|
|
{
|
|
|
|
NSDebugLog(@"result = %@",result);
|
|
|
|
result = [self superClassNameForClassNamed: result];
|
|
|
|
}
|
|
|
|
}
|
1999-12-21 11:38:49 +00:00
|
|
|
|
2002-10-13 06:04:05 +00:00
|
|
|
return result;
|
1999-12-21 11:38:49 +00:00
|
|
|
}
|
|
|
|
|
2003-02-13 13:32:59 +00:00
|
|
|
- (NSArray *) allSuperClassesOf: (NSString *)className
|
2002-12-15 07:30:35 +00:00
|
|
|
{
|
|
|
|
NSMutableArray *classes = [NSMutableArray array];
|
2006-09-28 02:31:06 +00:00
|
|
|
|
2005-07-13 06:19:16 +00:00
|
|
|
while (![self isRootClass: className] && className != nil)
|
2002-12-15 07:30:35 +00:00
|
|
|
{
|
|
|
|
NSDictionary *dict = [self classInfoForClassName: className];
|
2003-08-23 12:54:13 +00:00
|
|
|
if(dict != nil)
|
|
|
|
{
|
|
|
|
className = [dict objectForKey: @"Super"];
|
2005-05-21 15:10:14 +00:00
|
|
|
if(className != nil)
|
|
|
|
{
|
|
|
|
[classes insertObject: className atIndex: 0];
|
|
|
|
}
|
2003-08-23 12:54:13 +00:00
|
|
|
}
|
2004-03-04 04:01:09 +00:00
|
|
|
else
|
|
|
|
{
|
2005-04-14 04:40:48 +00:00
|
|
|
NSLog(@"Unable to find class named (%@), check that all palettes properly export classes to Gorm.",className);
|
2004-03-04 04:01:09 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-12-15 07:30:35 +00:00
|
|
|
}
|
2006-09-28 02:31:06 +00:00
|
|
|
|
2006-09-29 00:41:30 +00:00
|
|
|
return classes;
|
2002-12-15 07:30:35 +00:00
|
|
|
}
|
|
|
|
|
2003-07-15 04:20:09 +00:00
|
|
|
- (void) addActions: (NSArray *)actions forClassNamed: (NSString *)className
|
|
|
|
{
|
|
|
|
id action = nil;
|
|
|
|
NSEnumerator *e = [actions objectEnumerator];
|
|
|
|
while((action = [e nextObject]))
|
|
|
|
{
|
|
|
|
[self addAction: action forClassNamed: className];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) addOutlets: (NSArray *)outlets forClassNamed: (NSString *)className
|
|
|
|
{
|
|
|
|
id action = nil;
|
|
|
|
NSEnumerator *e = [outlets objectEnumerator];
|
|
|
|
while((action = [e nextObject]))
|
|
|
|
{
|
|
|
|
[self addOutlet: action forClassNamed: className];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-19 01:36:37 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2005-04-21 01:56:08 +00:00
|
|
|
else if([self isSuperclass: @"NSView" linkedToClass: className] ||
|
|
|
|
[className isEqualToString: @"NSView"])
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
2004-05-19 01:36:37 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-09-30 16:08:29 +00:00
|
|
|
- (NSString *) findClassByName: (NSString *)name
|
|
|
|
{
|
|
|
|
NSArray *classNames = [self allClassNames];
|
|
|
|
NSEnumerator *en = [classNames objectEnumerator];
|
|
|
|
NSString *className = nil;
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger namelen = [name length];
|
2006-09-30 16:08:29 +00:00
|
|
|
|
|
|
|
while((className = [en nextObject]) != nil)
|
|
|
|
{
|
2013-11-04 15:02:25 +00:00
|
|
|
NSInteger classlen = [className length];
|
2006-09-30 16:08:29 +00:00
|
|
|
if(namelen < classlen)
|
|
|
|
{
|
|
|
|
NSComparisonResult result =
|
|
|
|
[className compare: name
|
|
|
|
options: NSCaseInsensitiveSearch
|
|
|
|
range: ((NSRange){0, namelen})];
|
|
|
|
if(result == NSOrderedSame)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(namelen == classlen)
|
|
|
|
{
|
|
|
|
if([className caseInsensitiveCompare: name] == NSOrderedSame)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return className;
|
|
|
|
}
|
|
|
|
|
2023-07-08 16:53:09 +00:00
|
|
|
- (NSDictionary *) classInformation
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
return _classInformation;
|
2023-07-08 16:53:09 +00:00
|
|
|
}
|
|
|
|
|
2023-07-08 17:04:25 +00:00
|
|
|
- (NSDictionary *) customClassInformation
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSEnumerator *en = [_customClasses objectEnumerator];
|
2023-07-08 17:04:25 +00:00
|
|
|
NSMutableDictionary *result = [NSMutableDictionary dictionary];
|
|
|
|
NSString *name = nil;
|
|
|
|
|
|
|
|
while ((name = [en nextObject]) != nil)
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
NSDictionary *o = [_classInformation objectForKey: name];
|
2023-07-08 17:04:25 +00:00
|
|
|
[result setObject: o forKey: name];
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-10-22 18:39:24 +00:00
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
2003-10-18 06:20:45 +00:00
|
|
|
- (NSString *) description
|
|
|
|
{
|
|
|
|
return [NSString stringWithFormat: @"<%s: %lx> = %@",
|
|
|
|
GSClassNameFromObject(self),
|
|
|
|
(unsigned long)self,
|
2023-07-08 17:30:13 +00:00
|
|
|
_customClassMap];
|
2003-10-18 06:20:45 +00:00
|
|
|
}
|
2023-10-22 18:39:24 +00:00
|
|
|
#pragma GCC diagnostic pop
|
2004-11-13 05:06:15 +00:00
|
|
|
|
|
|
|
/** Helpful for debugging */
|
|
|
|
- (NSString *) dumpClassInformation
|
|
|
|
{
|
2023-07-08 17:30:13 +00:00
|
|
|
return [_classInformation description];
|
2004-11-13 05:06:15 +00:00
|
|
|
}
|
2023-07-08 18:14:46 +00:00
|
|
|
|
1999-12-21 11:38:49 +00:00
|
|
|
@end
|