Cleanup, memory leak fix.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/gorm/trunk@20290 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Gregory John Casamento 2004-11-04 06:46:26 +00:00
parent 2085f591e6
commit 5255ce829e
3 changed files with 160 additions and 101 deletions

View file

@ -1,4 +1,11 @@
2004-11-03 10:07 Gregory John Casamento <greg_casamento@yahoo.com>
2004-11-04 01:43 Gregory John Casamento <greg_casamento@yahoo.com>
* GormClassManager.m: Corrected a memory leak in
loadFromFile:.
* GormClassManager.h: Added FSF/GPL header and organized
the methods in the header according to function.
2004-11-03 22:07 Gregory John Casamento <greg_casamento@yahoo.com>
* GormClassManager.m: modified addNewActionToClassNamed: and
addNewOutletToClassNamed: so that the initial names for outlets

View file

@ -1,21 +1,50 @@
/* GormClassManager.h
*
* Copyright (C) 1999 Free Software Foundation, Inc.
*
* Author: Richard Frith-Macdonald <richard@brainstrom.co.uk>
* Author: Gregory John Casamento <greg_casamento@yahoo.com>
* Date: 1999, 2002
*
* This file is part of GNUstep.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <InterfaceBuilder/IBPalette.h>
#ifndef INCLUDED_GormClassManager_h
#define INCLUDED_GormClassManager_h
// the custom classes array will hold only those things which will be persisted
// to the .classes file. Since the overall list of classes will not change
// it seems that the only thing that we should save is the "delta" that being
// the custom classes. Once loaded they can be "merged" in with the list of
// base classes, in gui, to form the full list of classes.
// the custom classes and category arrays will hold only those things which
// will be persisted to the .classes file. Since the overall list of classes will
// not change it seems that the only thing that we should save is the "delta"
// that being the custom classes. Once loaded they can be "merged" in with the
// list of base classes, in gui, to form the full list of classes.
@interface GormClassManager : NSObject
{
NSMutableDictionary *classInformation;
NSMutableArray *customClasses;
NSMutableDictionary *customClassMap;
NSMutableArray *categoryClasses;
id document;
}
- (id) initWithDocument: (id)aDocument;
/** Managing actions and outlets */
- (void) addAction: (NSString*)anAction forObject: (id)anObject;
- (void) addOutlet: (NSString*)anOutlet forObject: (id)anObject;
- (NSArray*) allActionsForClassNamed: (NSString*)className;
@ -25,10 +54,6 @@
- (NSArray*) allOutletsForObject: (id)anObject;
- (NSArray*) extraActionsForObject: (id)anObject;
- (NSArray*) extraOutletsForObject: (id)anObject;
- (NSArray*) subClassesOf: (NSString *)superclass;
- (NSArray*) allSubclassesOf: (NSString *)superClass;
- (NSArray*) customSubClassesOf: (NSString *)superclass;
- (NSArray*) allCustomSubclassesOf: (NSString *)superclass;
- (void) removeAction: (NSString*)anAction forObject: (id)anObject;
- (void) removeOutlet: (NSString*)anOutlet forObject: (id)anObject;
- (void) removeAction: (NSString*)anAction fromClassNamed: (NSString*)anObject;
@ -41,9 +66,15 @@
- (NSString *) addNewOutletToClassNamed: (NSString *)name;
- (void) replaceAction: (NSString *)oldAction withAction: (NSString *)newAction forClassNamed: className;
- (void) replaceOutlet: (NSString *)oldOutlet withOutlet: (NSString *)newOutlet forClassNamed: className;
/** Managing classes and subclasses */
- (BOOL) renameClassNamed: (NSString *)oldName newName: (NSString*)name;
- (void) removeClassNamed: (NSString *)className;
- (NSString*) addClassWithSuperClassName: (NSString*)name;
- (NSArray*) subClassesOf: (NSString *)superclass;
- (NSArray*) allSubclassesOf: (NSString *)superClass;
- (NSArray*) customSubClassesOf: (NSString *)superclass;
- (NSArray*) allCustomSubclassesOf: (NSString *)superclass;
- (BOOL) addClassNamed: (NSString*)className
withSuperClassNamed: (NSString*)superClassName
@ -59,26 +90,21 @@
- (BOOL) setSuperClassNamed: (NSString*)superclass
forClassNamed: (NSString*)subclass;
- (NSString *)parentOfClass: (NSString *)aClass;
- (NSString*) superClassNameForClassNamed: (NSString*)className;
- (BOOL) isSuperclass: (NSString*)superclass
linkedToClass: (NSString*)subclass;
- (BOOL) makeSourceAndHeaderFilesForClass: (NSString*)className
withName:(NSString*)sourcePath
and:(NSString*)headerPath;
- (BOOL) parseHeader: (NSString *)headerPath;
- (BOOL) saveToFile: (NSString*)path;
- (BOOL) loadFromFile: (NSString*)path;
- (BOOL) loadCustomClasses: (NSString*)path;
/** Managing custom classes */
- (BOOL) isCustomClass: (NSString *)className;
- (BOOL) isNonCustomClass: (NSString *)className;
- (BOOL) isCategoryForClass: (NSString *)className;
- (BOOL) isKnownClass: (NSString *)className;
- (BOOL) isAction: (NSString *)actionName ofClass: (NSString *)className;
- (BOOL) isOutlet: (NSString *)outletName ofClass: (NSString *)className;
- (NSArray *) allSuperClassesOf: (NSString *)className;
- (BOOL) canInstantiateClassNamed: (NSString *)className;
// custom class support...
- (NSString *) customClassForObject: (id)object;
- (NSString *) customClassForName: (NSString *)name;
@ -90,7 +116,19 @@
- (void) setCustomClassMap: (NSMutableDictionary *)dict;
- (BOOL) isCustomClassMapEmpty;
- (NSString *) nonCustomSuperClassOf: (NSString *)className;
- (NSString *)parentOfClass: (NSString *)aClass;
/** Parsing and creating classes */
- (BOOL) makeSourceAndHeaderFilesForClass: (NSString*)className
withName:(NSString*)sourcePath
and:(NSString*)headerPath;
- (BOOL) parseHeader: (NSString *)headerPath;
/** loading and saving */
- (BOOL) saveToFile: (NSString*)path;
- (BOOL) loadFromFile: (NSString*)path;
- (BOOL) loadCustomClasses: (NSString*)path;
@end
#endif

View file

@ -31,14 +31,53 @@
#include <InterfaceBuilder/IBEditors.h>
#include <InterfaceBuilder/IBPalette.h>
@interface GormClassManager (Private)
/** Private methods not accesible from outside */
@interface GormClassManager (Private)
- (NSMutableDictionary*) classInfoForClassName: (NSString*)className;
- (NSMutableDictionary*) classInfoForObject: (id)anObject;
- (void) touch;
- (void) convertDictionary: (NSMutableDictionary *)dict;
@end
@implementation GormClassManager
- (void) _touch
- (id) initWithDocument: (id)aDocument
{
self = [super init];
if (self != nil)
{
NSBundle *bundle = [NSBundle mainBundle];
NSString *path;
document = aDocument; // the document retains us, this is for convenience
path = [bundle pathForResource: @"ClassInformation" ofType: @"plist"];
if (path == nil)
{
NSLog(@"ClassInformation.plist missing from resources");
}
else
{
GormPalettesManager *palettesManager = [(Gorm *)NSApp palettesManager];
// load the classes, initialize the custom class array and map..
[self loadFromFile: path];
customClasses = [[NSMutableArray alloc] initWithCapacity: 1];
customClassMap = [[NSMutableDictionary alloc] initWithCapacity: 10];
categoryClasses = [[NSMutableArray alloc] initWithCapacity: 1];
// add first responder so that it may be edited.
[customClasses addObject: @"FirstResponder"];
// add the imported classes to the class information list...
[classInformation addEntriesFromDictionary: [palettesManager importedClasses]];
}
}
return self;
}
- (void) touch
{
[[NSNotificationCenter defaultCenter]
postNotificationName: GormDidModifyClassNotification
@ -46,6 +85,12 @@
[document touch];
}
- (void) convertDictionary: (NSMutableDictionary *)dict
{
NSMutableArray *array = [classInformation allKeys];
[dict removeObjectsForKeys: array];
}
- (NSString*) addClassWithSuperClassName: (NSString*)name
{
if ([name isEqualToString: @"NSObject"]
@ -76,7 +121,7 @@
[classInformation setObject: classInfo forKey: newClassName];
[customClasses addObject: newClassName];
[self _touch];
[self touch];
[[NSNotificationCenter defaultCenter]
postNotificationName: GormDidAddClassNotification
@ -163,7 +208,7 @@
NSEnumerator *e = [actions objectEnumerator];
id action = nil;
[self _touch];
[self touch];
classInfo = [[NSMutableDictionary alloc] initWithCapacity: 3];
[classInfo setObject: outlets forKey: @"Outlets"];
@ -232,10 +277,7 @@
[[info objectForKey: @"AllActions"] insertObject: anAction atIndex: 0];
if(![className isEqualToString: @"FirstResponder"])
{
// if([self isSuperclass: @"NSResponder" linkedToClass: className])
{
[self addAction: anAction forClassNamed: @"FirstResponder"];
}
[self addAction: anAction forClassNamed: @"FirstResponder"];
}
while((subclassName = [en nextObject]) != nil)
@ -243,7 +285,7 @@
[self addAction: anAction forClassNamed: subclassName];
}
[self _touch];
[self touch];
}
- (void) addOutlet: (NSString*)outlet forObject: (id)anObject
@ -279,7 +321,7 @@
[self addOutlet: outlet forClassNamed: subclassName];
}
[self _touch];
[self touch];
}
- (void) replaceAction: (NSString *)oldAction
@ -317,7 +359,7 @@
[allActions replaceObjectAtIndex: all_index withObject: newAction];
}
[self _touch];
[self touch];
// add the action to all of the subclasses, in the "AllActions" section...
while((subclassName = [en nextObject]) != nil)
@ -327,10 +369,7 @@
if(![className isEqualToString: @"FirstResponder"])
{
// if([self isSuperclass: @"NSResponder" linkedToClass: className])
{
[self replaceAction: oldAction withAction: newAction forClassNamed: @"FirstResponder"];
}
[self replaceAction: oldAction withAction: newAction forClassNamed: @"FirstResponder"];
}
}
@ -369,7 +408,7 @@
[allOutlets replaceObjectAtIndex: all_index withObject: newOutlet];
}
[self _touch];
[self touch];
// add the action to all of the subclasses, in the "AllActions" section...
while((subclassName = [en nextObject]) != nil)
@ -416,15 +455,12 @@
}
}
[extraActions removeObject: anAction];
[self _touch];
[self touch];
}
if(![className isEqualToString: @"FirstResponder"])
{
// if([self isSuperclass: @"NSResponder" linkedToClass: className])
{
[self removeAction: anAction fromClassNamed: @"FirstResponder"];
}
[self removeAction: anAction fromClassNamed: @"FirstResponder"];
}
while((subclassName = [en nextObject]) != nil)
@ -466,7 +502,7 @@
}
}
[extraOutlets removeObject: anOutlet];
[self _touch];
[self touch];
}
while((subclassName = [en nextObject]) != nil)
@ -825,41 +861,6 @@
return [info objectForKey: @"ExtraOutlets"];
}
- (id) initWithDocument: (id)aDocument
{
self = [super init];
if (self != nil)
{
NSBundle *bundle = [NSBundle mainBundle];
NSString *path;
document = aDocument; // the document retains us, this is for convenience
path = [bundle pathForResource: @"ClassInformation" ofType: @"plist"];
if (path == nil)
{
NSLog(@"ClassInformation.plist missing from resources");
}
else
{
GormPalettesManager *palettesManager = [(Gorm *)NSApp palettesManager];
// load the classes, initialize the custom class array and map..
[self loadFromFile: path];
customClasses = [[NSMutableArray alloc] initWithCapacity: 1];
customClassMap = [[NSMutableDictionary alloc] initWithCapacity: 10];
// add first responder so that it may be edited.
[customClasses addObject: @"FirstResponder"];
// add the imported classes to the class information list...
[classInformation addEntriesFromDictionary: [palettesManager importedClasses]];
}
}
return self;
}
- (void) allSubclassesOf: (NSString *)superclass
referenceClassList: (NSArray *)classList
intoArray: (NSMutableArray *)array
@ -982,7 +983,7 @@
}
[classInformation removeObjectForKey: className];
[self _touch];
[self touch];
[[NSNotificationCenter defaultCenter]
postNotificationName: GormDidDeleteClassNotification
@ -1042,7 +1043,7 @@
forClassNamed: sc];
}
[self _touch];
[self touch];
}
else
NSLog(@"customClass not found %@",oldName);
@ -1063,8 +1064,10 @@
{
NSMutableDictionary *ci;
NSEnumerator *enumerator;
id key;
id key;
NSMutableArray *classesToSave;
classesToSave = [customClasses arrayByAddingObjectsFromArray: categoryClasses];
ci = AUTORELEASE([[NSMutableDictionary alloc] initWithCapacity: 0]);
enumerator = [customClasses objectEnumerator];
while ((key = [enumerator nextObject]) != nil)
@ -1074,6 +1077,7 @@
id obj;
id extraObj;
// superclass...
classInfo = [classInformation objectForKey: key];
newInfo = [NSMutableDictionary new];
[ci setObject: newInfo forKey: key];
@ -1083,6 +1087,8 @@
{
[newInfo setObject: obj forKey: @"Super"];
}
// outlets...
obj = [classInfo objectForKey: @"Outlets"];
extraObj = [classInfo objectForKey: @"ExtraOutlets"];
if (obj && extraObj)
@ -1097,6 +1103,8 @@
{
[newInfo setObject: obj forKey: @"Outlets"];
}
// actions...
obj = [classInfo objectForKey: @"Actions"];
extraObj = [classInfo objectForKey: @"ExtraActions"];
if (obj && extraObj)
@ -1125,31 +1133,31 @@
NSDebugLog(@"Load from file %@",path);
dict = [NSDictionary dictionaryWithContentsOfFile: path];
// customClasses = [NSMutableArray arrayWithCapacity: 1];
if (dict == nil)
{
NSLog(@"Could not load classes dictionary");
return NO;
}
/*
* Convert property-list data into a mutable structure.
*/
RELEASE(classInformation);
classInformation = [NSMutableDictionary new];
RETAIN(classInformation); // released in dealloc...
classInformation = [[NSMutableDictionary alloc] init];
enumerator = [dict keyEnumerator];
while ((key = [enumerator nextObject]) != nil)
{
NSDictionary *classInfo = [dict objectForKey: key];
NSMutableDictionary *newInfo;
NSMutableDictionary *oldInfo;
id obj;
NSDictionary *classInfo = [dict objectForKey: key];
NSMutableDictionary *newInfo;
NSMutableDictionary *oldInfo;
id obj;
newInfo = [NSMutableDictionary new];
oldInfo = [classInformation objectForKey: key];
[classInformation setObject: newInfo forKey: key];
// superclass
obj = [classInfo objectForKey: @"Super"];
if (obj != nil)
{
@ -1163,8 +1171,9 @@
obj = [obj mutableCopy];
[obj sortUsingSelector: @selector(compare:)];
[newInfo setObject: obj forKey: @"Outlets"];
RELEASE(obj);
}
// actions
obj = [classInfo objectForKey: @"Actions"];
if (obj != nil)
@ -1172,22 +1181,19 @@
obj = [obj mutableCopy];
[obj sortUsingSelector: @selector(compare:)];
[newInfo setObject: obj forKey: @"Actions"];
RELEASE(obj);
}
}
return YES;
}
- (void) _convertDictionary: (NSMutableDictionary *)dict
{
NSMutableArray *array = [classInformation allKeys];
[dict removeObjectsForKeys: array];
}
// this method will load the custom classes and merge them with the
// Class information loaded at initialization time.
- (BOOL) loadCustomClasses: (NSString *)path
{
NSMutableDictionary *dict;
NSEnumerator *en;
id obj;
NSDebugLog(@"Load custom classes from file %@",path);
@ -1207,7 +1213,7 @@
if ([[dict allKeys] containsObject: @"NSObject"])
{
NSLog(@"The file being loaded is in the old .classes format. Updating..");
[self _convertDictionary: dict];
[self convertDictionary: dict];
}
[customClasses addObjectsFromArray: [dict allKeys]];
@ -1218,8 +1224,17 @@
- (BOOL) isCustomClass: (NSString *)className
{
return ([customClasses indexOfObject: className] != NSNotFound); // &&
// ![className isEqualToString: @"FirstResponder"]);
return ([customClasses indexOfObject: className] != NSNotFound);
}
- (BOOL) isNonCustomClass: (NSString *)className
{
return !([self isCustomClass: className]);
}
- (BOOL) isCategoryForClass: (NSString *)className
{
return ([categoryClasses indexOfObject: className] != NSNotFound);
}
- (BOOL) isKnownClass: (NSString *)className
@ -1445,7 +1460,6 @@
{
NSString *name = [document nameForObject: object];
NSString *result = [self customClassForName: name];
// NSString *result = [customClassMap objectForKey: name];
NSDebugLog(@"in customClassForObject: object = %@, name = %@, result = %@, customClassMap = %@",
object, name, result, customClassMap);
return result;