Nib support changes.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/gorm/trunk@23043 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Gregory John Casamento 2006-06-10 13:34:44 +00:00
parent 5fa3ae3247
commit 145a8afd69
16 changed files with 1507 additions and 699 deletions

View file

@ -1,3 +1,22 @@
2006-06-10 09:24 Gregory John Casamento <greg_casamento@yahoo.com>
* GormCore/GModelDecoder.m: Changes to make this compile with
new modifications.
* GormCore/GNUmakefile: Addition of new files.
* GormCore/GormCustomView.m:Encoding changes for NSCustomView.
* GormCore/GormDocumentController.m: Removed touch, so that it
is possible to quit when first creating a new document, this is the
way other document oriented apps behave.
* GormCore/GormDocument.[hm]: Added container methods and
coding methods.
* GormCore/GormGormWrapperBuilder.m: Class whic writes gorm files.
* GormCore/GormGormWrapperLoader.m: Class which loads gorm files
* GormCore/GormPrivate.[hm]: Simplification of init call to
GormObjectProxy.
* GormCore/GormWrapperBuilder.[hm]: Wrapper builder
* GormCore/GormWrapperLoader.[hm]: Wrapper loader
* Gorm.m: Change testInterface to encode the doc.
2006-06-05 21:20 Gregory John Casamento <greg_casamento@yahoo.com>
* GormCore/GormDocumentController.m: touches the initial document

9
Gorm.m
View file

@ -42,7 +42,7 @@
NSMutableArray *documents;
BOOL isConnecting;
BOOL isTesting;
id testContainer;
id testContainer;
id gormMenu;
NSMenu *mainMenu; // saves the main menu...
NSMenu *servicesMenu; // saves the services menu...
@ -451,7 +451,7 @@
// do not allow custom classes during testing.
[GSClassSwapper setIsInInterfaceBuilder: YES];
[archiver encodeRootObject: [activeDoc container]];
[archiver encodeRootObject: activeDoc];
data = RETAIN([archiver archiverData]); // Released below...
[activeDoc endArchiving];
RELEASE(archiver);
@ -478,6 +478,7 @@
NSMutableDictionary *nameTable = [testContainer nameTable];
// initialize the context.
RETAIN(testContainer);
topObjects = [[NSMutableArray alloc] init];
context = [NSDictionary dictionaryWithObjectsAndKeys: topObjects,
@"NSTopLevelObjects", self, @"NSOwner", nil];
@ -859,8 +860,8 @@
DESTROY(testingWindows);
// deallocate top level objects
RELEASE(topObjects);
// deallocate
RELEASE(testContainer);
return self;
}

View file

@ -563,11 +563,11 @@ static BOOL gormFileOwnerDecoded;
[newcon setSource: source];
[newcon setDestination: (dest != nil)?dest:[self firstResponder]];
[newcon setLabel: [con label]];
[[container connections] addObject: newcon];
[[self connections] addObject: newcon];
}
// make sure that all of the actions on the application's delegate object are also added to FirstResponder.
enumerator = [[container connections] objectEnumerator];
enumerator = [connections objectEnumerator];
while ((con = [enumerator nextObject]) != nil)
{
if([con isKindOfClass: [NSNibControlConnector class]])

View file

@ -86,6 +86,8 @@ GormCore_HEADER_FILES = \
GormViewWithContentViewEditor.h \
GormViewWithSubviewsEditor.h \
GormWindowEditor.h \
GormWrapperBuilder.h \
GormWrapperLoader.h \
NSCell+GormAdditions.h \
NSColorWell+GormExtensions.h \
NSFontManager+GormExtensions.h \
@ -139,6 +141,10 @@ GormCore_OBJC_FILES = \
GormViewWithContentViewEditor.m \
GormViewWithSubviewsEditor.m \
GormWindowEditor.m \
GormWrapperBuilder.m \
GormWrapperLoader.m \
GormGormWrapperBuilder.m \
GormGormWrapperLoader.m \
NSCell+GormAdditions.m \
NSColorWell+GormExtensions.m \
NSFontManager+GormExtensions.m \

View file

@ -32,6 +32,7 @@
#include <AppKit/NSNibLoading.h>
#include <GNUstepGUI/GSNibTemplates.h>
#include <GNUstepGUI/GSNibCompatibility.h>
@class GSCustomView;
@ -87,38 +88,50 @@
- (id) initWithCoder: (NSCoder*)aCoder
{
int version = [aCoder versionForClassName:
NSStringFromClass([GSCustomView class])];
if (version == 1)
if([aCoder allowsKeyedCoding])
{
NSString *string;
// do not decode super. We need to maintain mapping to NibItems
string = [aCoder decodeObject];
_frame = [aCoder decodeRect];
[self initWithFrame: _frame];
[aCoder decodeValueOfObjCType: @encode(unsigned int)
at: &_autoresizingMask];
[self setClassName: string];
return self;
}
else if (version == 0)
{
NSString *string;
// do not decode super. We need to maintain mapping to NibItems
string = [aCoder decodeObject];
_frame = [aCoder decodeRect];
[self initWithFrame: _frame];
[self setClassName: string];
return self;
NSCustomView *customView = [[NSCustomView alloc] initWithCoder: aCoder];
[self initWithFrame: [customView frame]];
[self setClassName: [customView className]];
_autoresizingMask = [customView autoresizingMask];
RELEASE(customView);
}
else
{
NSLog(@"no initWithCoder for version");
RELEASE(self);
return nil;
int version = [aCoder versionForClassName:
NSStringFromClass([GSCustomView class])];
if (version == 1)
{
NSString *string;
// do not decode super. We need to maintain mapping to NibItems
string = [aCoder decodeObject];
_frame = [aCoder decodeRect];
[self initWithFrame: _frame];
[aCoder decodeValueOfObjCType: @encode(unsigned int)
at: &_autoresizingMask];
[self setClassName: string];
return self;
}
else if (version == 0)
{
NSString *string;
// do not decode super. We need to maintain mapping to NibItems
string = [aCoder decodeObject];
_frame = [aCoder decodeRect];
[self initWithFrame: _frame];
[self setClassName: string];
return self;
}
else
{
NSLog(@"no initWithCoder for version");
RELEASE(self);
return nil;
}
}
return nil;
}
@end

View file

@ -31,7 +31,7 @@
#include <GNUstepGUI/GSNibTemplates.h>
#include <InterfaceBuilder/InterfaceBuilder.h>
@class GormClassManager, GormClassEditor, GormObjectProxy, GormFilesOwner;
@class GormClassManager, GormClassEditor, GormObjectProxy, GormFilesOwner, GormFilePrefsManager;
/*
* Each document has a GormFirstResponder object that is used as a placeholder
@ -42,7 +42,7 @@
}
@end
@interface GormDocument : NSDocument <IBDocuments>
@interface GormDocument : NSDocument <IBDocuments, GSNibContainer, NSCoding>
{
GormClassManager *classManager;
GormFilesOwner *filesOwner;
@ -70,14 +70,20 @@
id lastEditor;
BOOL isOlderArchive;
id filePrefsView;
id filePrefsManager;
GormFilePrefsManager *filePrefsManager;
NSWindow *filePrefsWindow;
NSMutableArray *resourceManagers;
NSData *infoData; /* data.info contents */
NSMutableArray *images; /* temporary storage for images. */
NSMutableArray *sounds; /* temporary storage for sounds. */
NSFileWrapper *scmDirWrapper;
id<GSNibContainer, NSObject> container;
NSFileWrapper *scmWrapper;
// container data structures
NSMutableDictionary *nameTable;
NSMutableArray *connections;
NSMutableSet *topLevelObjects;
NSMutableSet *visibleWindows;
NSMutableSet *deferredWindows;
}
/* Archiving objects */
@ -146,11 +152,6 @@
*/
- (NSWindow*) window;
/**
* Return the container object associated with this document.
*/
- (id<GSNibContainer>) container;
/**
* Returns YES, if obj is a top level object.
*/
@ -311,9 +312,66 @@
- (NSWindow*) windowAndRect: (NSRect*)r forObject: (id)object;
/**
* The container class to use in editing....
* Save the SCM directory.
*/
- (Class) containerClass;
- (void) setSCMWrapper: (NSFileWrapper *) wrapper;
/**
* Save the SCM directory.
*/
- (NSFileWrapper *) scmWrapper;
/**
* Images
*/
- (NSArray *) images;
/**
* Sounds
*/
- (NSArray *) sounds;
/**
* Images
*/
- (void) setImages: (NSArray *) imgs;
/**
* Sounds
*/
- (void) setSounds: (NSArray *) snds;
/**
* File's Owner
*/
- (GormFilesOwner *) filesOwner;
/**
* File preferences.
*/
- (GormFilePrefsManager *) filePrefsManager;
/**
* Windows visible at launch...
*/
- (NSSet *) visibleWindows;
/**
* Windows deferred.
*/
- (NSSet *) deferredWindows;
- (void) setDocumentOpen: (BOOL) flag;
- (BOOL) isDocumentOpen;
- (void) setInfoData: (NSData *)data;
- (NSData *) infoData;
- (void) setOlderArchive: (BOOL)flag;
- (BOOL) isOlderArchive;
@end
@interface GormDocument (MenuValidation)

File diff suppressed because it is too large Load diff

View file

@ -188,7 +188,6 @@
// set the filetype and touch the document.
[doc setFileType: @"GSGormFileType"];
[doc touch];
}
@end

View file

@ -0,0 +1,195 @@
/* GormWrapperBuilder
*
* This class is a subclass of the NSDocumentController
*
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* Author: Gregory John Casamento <greg_casamento@yahoo.com>
* Date: 2006
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
*/
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
#include <GNUstepGUI/GSNibTemplates.h>
#include <GormCore/GormWrapperBuilder.h>
#include <GormCore/GormClassManager.h>
#include <GormCore/GormFilePrefsManager.h>
#include <GormCore/GormDocument.h>
#include <GormCore/GormProtocol.h>
#include <GormCore/GormPalettesManager.h>
@interface GSNibContainer (BuilderAdditions)
- (id) initWithDocument: (GormDocument *)document;
@end;
@implementation GSNibContainer (BuilderAdditions)
- (id) initWithDocument: (GormDocument *)document
{
if((self = [self init]) != nil)
{
NSMutableArray *visible = [nameTable objectForKey: @"NSVisible"];
NSMutableArray *deferred = [nameTable objectForKey: @"NSDeferred"];
// Create the container for the .gorm file...
[nameTable addEntriesFromDictionary: [document nameTable]];
[topLevelObjects addObjectsFromArray: [[document topLevelObjects] allObjects]];
[visible addObjectsFromArray: [[document visibleWindows] allObjects]];
[deferred addObjectsFromArray: [[document deferredWindows] allObjects]];
}
return self;
}
@end
@interface GormGormWrapperBuilder : GormWrapperBuilder
@end
@implementation GormGormWrapperBuilder
+ (NSString *) type
{
return @"GSGormFileType";
}
/**
* Private method which iterates through the list of custom classes and instructs
* the archiver to replace the actual object with template during the archiving
* process.
*/
- (void) _replaceObjectsWithTemplates: (NSArchiver *)archiver
{
NSEnumerator *en = [[document nameTable] keyEnumerator];
GormClassManager *classManager = [document classManager];
GormFilePrefsManager *filePrefsManager = [document filePrefsManager];
id key = nil;
// loop through all custom objects and windows
while((key = [en nextObject]) != nil)
{
id customClass = [classManager customClassForName: key];
id object = [document objectForName: key];
id template = nil;
if(customClass != nil)
{
NSString *superClass = [classManager nonCustomSuperClassOf: customClass];
template = [GSTemplateFactory templateForObject: object
withClassName: customClass
withSuperClassName: superClass];
}
else if([object isKindOfClass: [NSWindow class]]
&& [filePrefsManager versionOfClass: @"GSWindowTemplate"] > 0)
{
template = [GSTemplateFactory templateForObject: object
withClassName: [object className]
withSuperClassName: [object className]];
}
// if the template has been created, replace the object with it.
if(template != nil)
{
// if the object is deferrable, then set the flag appropriately.
if([template respondsToSelector: @selector(setDeferFlag:)])
{
[template setDeferFlag: [document objectIsDeferred: object]];
}
// if the object can accept autoposition information
if([object respondsToSelector: @selector(autoPositionMask)])
{
int mask = [object autoPositionMask];
if([template respondsToSelector: @selector(setAutoPositionMask:)])
{
[template setAutoPositionMask: mask];
}
}
// replace the object with the template.
[archiver replaceObject: object withObject: template];
}
}
}
- (NSMutableDictionary *)buildFileWrapperDictionaryWithDocument: (GormDocument *)doc
{
NSArchiver *archiver = nil;
NSMutableData *archiverData = nil;
NSString *gormPath = @"objects.gorm";
NSString *classesPath = @"data.classes";
NSString *infoPath = @"data.info";
GormPalettesManager *palettesManager = [(id<Gorm>)NSApp palettesManager];
NSDictionary *substituteClasses = [palettesManager substituteClasses];
NSEnumerator *en = [substituteClasses keyEnumerator];
NSString *subClassName = nil;
NSFileWrapper *fileWrapper = nil;
NSMutableDictionary *fileWrappers = [super buildFileWrapperDictionaryWithDocument: doc];
if(fileWrappers)
{
GormClassManager *classManager = [document classManager];
GormFilePrefsManager *filePrefsManager = [document filePrefsManager];
GSNibContainer *container = [[GSNibContainer alloc] initWithDocument: document];
/*
* Set up archiving...
*/
archiverData = [NSMutableData dataWithCapacity: 0];
archiver = [[NSArchiver alloc] initForWritingWithMutableData: archiverData];
/*
* Special gorm classes to their archive equivalents.
*/
[archiver encodeClassName: @"GormObjectProxy"
intoClassName: @"GSNibItem"];
[archiver encodeClassName: @"GormCustomView"
intoClassName: @"GSCustomView"];
while((subClassName = [en nextObject]) != nil)
{
NSString *realClassName = [substituteClasses objectForKey: subClassName];
[archiver encodeClassName: subClassName
intoClassName: realClassName];
}
/*
* Initialize templates
*/
[self _replaceObjectsWithTemplates: archiver];
[archiver encodeRootObject: container];
RELEASE(archiver); // We're done with the archiver here..
/*
* Add the gorm, info and classes files to the package.
*/
fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents: archiverData];
[fileWrappers setObject: fileWrapper forKey: gormPath];
RELEASE(fileWrapper);
fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents: [classManager data]];
[fileWrappers setObject: fileWrapper forKey: classesPath];
RELEASE(fileWrapper);
fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents: [filePrefsManager data]];
[fileWrappers setObject: fileWrapper forKey: infoPath];
RELEASE(fileWrapper);
// release the container...
RELEASE(container);
}
return fileWrappers;
}
@end

View file

@ -0,0 +1,410 @@
/* GormDocumentController.m
*
* This class is a subclass of the NSDocumentController
*
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* Author: Gregory John Casamento <greg_casamento@yahoo.com>
* Date: 2006
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
*/
#include <GormCore/GormWrapperLoader.h>
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
#include <GormCore/GormPalettesManager.h>
#include <GormCore/GormClassManager.h>
#include <GormCore/GormImage.h>
#include <GormCore/GormSound.h>
#include <GormCore/GormPrivate.h>
#include <GormCore/NSView+GormExtensions.h>
#include <GormCore/GormFunctions.h>
@interface GormGormWrapperLoader : GormWrapperLoader
@end
@implementation GormGormWrapperLoader
+ (NSString *) type
{
return @"GSGormFileType";
}
/**
* The sole purpose of this method is to clean up .gorm files from older
* versions of Gorm which might have some dangling references. This method
* may be added to as time goes on to make sure that it's possible
* to repair old .gorm files.
*/
- (void) _repairFile
{
NSEnumerator *en = [[[document nameTable] allKeys] objectEnumerator];
NSString *key = nil;
NSRunAlertPanel(_(@"Warning"),
_(@"You are running with 'GormRepairFileOnLoad' set to YES."),
nil, nil, nil);
while((key = [en nextObject]) != nil)
{
id obj = [[document nameTable] objectForKey: key];
if([obj isKindOfClass: [NSMenu class]] && ![key isEqual: @"NSMenu"])
{
id sm = [obj supermenu];
if(sm == nil)
{
NSArray *menus = findAll(obj);
NSLog(@"Found and removed a dangling menu %@, %@.",obj,[document nameForObject: obj]);
[document detachObjects: menus];
[document detachObject: obj];
// Since the menu is a top level object, it is not retained by
// anything else. When it was unarchived it was autoreleased, and
// the detach also does a release. Unfortunately, this causes a
// crash, so this extra retain is only here to stave off the
// release, so the autorelease can release the menu when it should.
RETAIN(obj); // extra retain to stave off autorelease...
}
}
if([obj isKindOfClass: [NSMenuItem class]])
{
id m = [obj menu];
if(m == nil)
{
id sm = [obj submenu];
NSLog(@"Found and removed a dangling menu item %@, %@.",obj,[document nameForObject: obj]);
[document detachObject: obj];
// if there are any submenus, detach those as well.
if(sm != nil)
{
NSArray *menus = findAll(sm);
[document detachObjects: menus];
}
}
}
/**
* If it's a view and it does't have a window *AND* it's not a top level object
* then it's not a standalone view, it's an orphan. Delete it.
*/
if([obj isKindOfClass: [NSView class]])
{
if([obj window] == nil &&
[[document topLevelObjects] containsObject: obj] == NO &&
[obj hasSuperviewKindOfClass: [NSTabView class]] == NO)
{
NSLog(@"Found and removed an orphan view %@, %@",obj,[document nameForObject: obj]);
[document detachObject: obj];
}
}
}
}
/**
* Private method. Determines if the document contains an instance of a given
* class or one of it's subclasses.
*/
- (BOOL) _containsKindOfClass: (Class)cls
{
NSEnumerator *en = [[document nameTable] objectEnumerator];
id obj = nil;
while((obj = [en nextObject]) != nil)
{
if([obj isKindOfClass: cls])
{
return YES;
}
}
return NO;
}
- (BOOL) loadFileWrapper: (NSFileWrapper *)wrapper withDocument: (GormDocument *) doc
{
NS_DURING
{
NSMutableDictionary *cc = nil;
NSData *data = nil;
NSData *classes = nil;
NSUnarchiver *u = nil;
NSEnumerator *enumerator = nil;
id <IBConnectors> con = nil;
NSString *ownerClass, *key = nil;
BOOL repairFile = [[NSUserDefaults standardUserDefaults] boolForKey: @"GormRepairFileOnLoad"];
GormPalettesManager *palettesManager = [(id<Gorm>)NSApp palettesManager];
NSDictionary *substituteClasses = [palettesManager substituteClasses];
NSEnumerator *en = [substituteClasses keyEnumerator];
NSString *subClassName = nil;
unsigned int version = NSNotFound;
NSDictionary *fileWrappers = nil;
if ([super loadFileWrapper: wrapper withDocument: doc])
{
GormClassManager *classManager = [document classManager];
NSArray *imageFileTypes = [NSImage imageFileTypes];
NSArray *soundFileTypes = [NSSound soundUnfilteredFileTypes];
NSMutableArray *images = [[NSMutableArray alloc] init];
NSMutableArray *sounds = [[NSMutableArray alloc] init];
key = nil;
fileWrappers = [wrapper fileWrappers];
// [ saveSCMDirectory: fileWrappers];
enumerator = [fileWrappers keyEnumerator];
while((key = [enumerator nextObject]) != nil)
{
NSFileWrapper *fw = [fileWrappers objectForKey: key];
if([fw isRegularFile])
{
NSData *fileData = [fw regularFileContents];
if([key isEqual: @"objects.gorm"])
{
data = fileData;
}
else if([key isEqual: @"data.info"])
{
[document setInfoData: fileData];
}
else if([key isEqual: @"data.classes"])
{
classes = fileData;
// load the custom classes...
if (![classManager loadCustomClassesWithData: classes])
{
NSRunAlertPanel(_(@"Problem Loading"),
_(@"Could not open the associated classes file.\n"
@"You won't be able to edit connections on custom classes"),
_(@"OK"), nil, nil);
}
}
else if ([imageFileTypes containsObject: [key pathExtension]])
{
[images addObject: [GormImage imageForData: fileData withFileName: key inWrapper: YES]];
}
else if ([soundFileTypes containsObject: [key pathExtension]])
{
[sounds addObject: [GormSound soundForData: fileData withFileName: key inWrapper: YES]];
}
}
}
// check the data...
if (data == nil || [document infoData] == nil || classes == nil)
{
return NO;
}
/*
* Create an unarchiver, and use it to unarchive the gorm file while
* handling class replacement so that standard objects understood
* by the gui library are converted to their Gorm internal equivalents.
*/
u = [[NSUnarchiver alloc] initForReadingWithData: data];
/*
* Special internal classes
*/
[u decodeClassName: @"GSNibItem"
asClassName: @"GormObjectProxy"];
[u decodeClassName: @"GSCustomView"
asClassName: @"GormCustomView"];
/*
* Substitute any classes specified by the palettes...
*/
while((subClassName = [en nextObject]) != nil)
{
NSString *realClassName = [substituteClasses objectForKey: subClassName];
[u decodeClassName: realClassName
asClassName: subClassName];
}
// turn off custom classes.
[GSClassSwapper setIsInInterfaceBuilder: YES];
GSNibContainer *container = [u decodeObject];
if (container == nil || [container isKindOfClass: [GSNibContainer class]] == NO)
{
return NO;
}
// turn on custom classes.
[GSClassSwapper setIsInInterfaceBuilder: NO];
/*
* Retrieve the custom class data and refresh the classes view...
*/
NSMutableDictionary *nt = [container nameTable];
cc = [nt objectForKey: @"GSCustomClassMap"];
if (cc == nil)
{
cc = [NSMutableDictionary dictionary]; // create an empty one.
[nt setObject: cc forKey: @"GSCustomClassMap"];
}
[classManager setCustomClassMap: cc];
[nt removeObjectForKey: @"GSCustomClassMap"];
//
// Get all of the visible objects...
//
NSArray *visible = [nt objectForKey: @"NSVisible"];
id visObj = nil;
enumerator = [visible objectEnumerator];
while((visObj = [enumerator nextObject]) != nil)
{
[document setObject: visObj isVisibleAtLaunch: YES];
}
[nt removeObjectForKey: @"NSVisible"];
//
// Get all of the deferred objects...
//
NSArray *deferred = [nt objectForKey: @"NSDeferred"];
id defObj = nil;
enumerator = [deferred objectEnumerator];
while((defObj = [enumerator nextObject]) != nil)
{
[document setObject: defObj isDeferred: YES];
}
[nt removeObjectForKey: @"NSDeferred"];
/*
* In the newly loaded nib container, we change all the connectors
* to hold the objects rather than their names (using our own dummy
* object as the 'NSOwner'.
*/
ownerClass = [nt objectForKey: @"NSOwner"];
if (ownerClass)
{
[[document filesOwner] setClassName: ownerClass];
}
[[container nameTable] removeObjectForKey: @"NSOwner"];
[[container nameTable] removeObjectForKey: @"NSFirst"];
//
// Add entries...
//
[[document nameTable] addEntriesFromDictionary: nt];
//
// Add top level items...
//
NSArray *objs = [[container topLevelObjects] allObjects];
[[document topLevelObjects] addObjectsFromArray: objs];
/* Iterate over the contents of nameTable and create the connections */
nt = [document nameTable];
enumerator = [[container connections] objectEnumerator];
while ((con = [enumerator nextObject]) != nil)
{
NSString *name;
id obj;
name = (NSString*)[con source];
obj = [nt objectForKey: name];
[con setSource: obj];
name = (NSString*)[con destination];
obj = [nt objectForKey: name];
[con setDestination: obj];
}
/*
* If the GSNibContainer version is 0, we need to add the top level objects
* to the list so that they can be properly processed.
*/
if([u versionForClassName: NSStringFromClass([GSNibContainer class])] == 0)
{
id obj;
NSEnumerator *en = [nt objectEnumerator];
// get all of the GSNibItem subclasses which could be top level objects
while((obj = [en nextObject]) != nil)
{
if([obj isKindOfClass: [GSNibItem class]] &&
[obj isKindOfClass: [GSCustomView class]] == NO)
{
[[container topLevelObjects] addObject: obj];
}
}
[document setOlderArchive: YES];
}
/*
* If the GSWindowTemplate version is 0, we need to let Gorm know that this is
* an older archive. Also, if the window template is not in the archive we know
* it was made by an older version of Gorm.
*/
version = [u versionForClassName: NSStringFromClass([GSWindowTemplate class])];
if(version == NSNotFound && [self _containsKindOfClass: [NSWindow class]])
{
[document setOlderArchive: YES];
}
/*
* repair the .gorm file, if needed.
*/
if(repairFile)
{
[self _repairFile];
}
/*
* Rebuild the mapping from object to name for the nameTable...
*/
[document rebuildObjToNameMapping];
NSDebugLog(@"nameTable = %@",[container nameTable]);
// awaken all elements after the load is completed.
enumerator = [nt keyEnumerator];
while ((key = [enumerator nextObject]) != nil)
{
id o = [nt objectForKey: key];
if ([o respondsToSelector: @selector(awakeFromDocument:)])
{
[o awakeFromDocument: document];
}
}
// document opened...
[document setDocumentOpen: YES];
// release the unarchiver..
RELEASE(u);
}
else
{
return NO;
}
}
NS_HANDLER
{
NSRunAlertPanel(_(@"Problem Loading"),
[NSString stringWithFormat: @"Failed to load file. Exception: %@",[localException reason]],
_(@"OK"), nil, nil);
return NO;
}
NS_ENDHANDLER;
// if we made it here, then it was a success....
return YES;
}
@end

View file

@ -51,7 +51,8 @@ extern NSString *GormResizeCellNotification;
// templates
@interface GSNibItem (GormAdditions)
- initWithClassName: (NSString*)className frame: (NSRect)frame;
- (id) initWithClassName: (NSString*)className;
- (id) initWithClassName: (NSString*)className frame: (NSRect)frame;
- (NSString*) className;
@end

View file

@ -49,15 +49,23 @@ static BOOL _isInInterfaceBuilder = NO;
#include "GormViewWithContentViewEditor.h"
@implementation GSNibItem (GormAdditions)
- initWithClassName: (NSString*)className frame: (NSRect)frame
- (id) initWithClassName: (NSString*)className frame: (NSRect)frame
{
self = [super init];
theClass = [className copy];
theFrame = frame;
if((self = [super init]) != nil)
{
theClass = [className copy];
theFrame = frame;
}
return self;
}
- (id) initWithClassName: (NSString*)className
{
return [self initWithClassName: className
frame: NSMakeRect(0,0,0,0)];
}
- (NSString*) className
{
return theClass;
@ -109,42 +117,50 @@ static BOOL _isInInterfaceBuilder = NO;
*/
- (id) initWithCoder: (NSCoder*)aCoder
{
int version = [aCoder versionForClassName:
NSStringFromClass([GSNibItem class])];
if (version == NSNotFound)
if([aCoder allowsKeyedCoding])
{
NSLog(@"no GSNibItem");
version = [aCoder versionForClassName:
NSStringFromClass([GormObjectProxy class])];
}
if (version == 0)
{
// do not decode super (it would try to morph into theClass ! )
[aCoder decodeValueOfObjCType: @encode(id) at: &theClass];
theFrame = [aCoder decodeRect];
RETAIN(theClass); // release in dealloc of GSNibItem...
return self;
}
else if (version == 1)
{
// do not decode super (it would try to morph into theClass ! )
[aCoder decodeValueOfObjCType: @encode(id) at: &theClass];
theFrame = [aCoder decodeRect];
[aCoder decodeValueOfObjCType: @encode(unsigned int)
at: &autoresizingMask];
RETAIN(theClass); // release in dealloc of GSNibItem...
return self;
}
else
{
NSLog(@"no initWithCoder for version %d", version);
RELEASE(self);
return nil;
int version = [aCoder versionForClassName:
NSStringFromClass([GSNibItem class])];
if (version == NSNotFound)
{
NSLog(@"no GSNibItem");
version = [aCoder versionForClassName:
NSStringFromClass([GormObjectProxy class])];
}
if (version == 0)
{
// do not decode super (it would try to morph into theClass ! )
[aCoder decodeValueOfObjCType: @encode(id) at: &theClass];
theFrame = [aCoder decodeRect];
RETAIN(theClass); // release in dealloc of GSNibItem...
return self;
}
else if (version == 1)
{
// do not decode super (it would try to morph into theClass ! )
[aCoder decodeValueOfObjCType: @encode(id) at: &theClass];
theFrame = [aCoder decodeRect];
[aCoder decodeValueOfObjCType: @encode(unsigned int)
at: &autoresizingMask];
RETAIN(theClass); // release in dealloc of GSNibItem...
return self;
}
else
{
NSLog(@"no initWithCoder for version %d", version);
RELEASE(self);
return nil;
}
}
return nil;
}
- (NSString*) inspectorClassName

View file

@ -0,0 +1,51 @@
/* GormWrapperBuilder
*
* This class is a subclass of the NSDocumentController
*
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* Author: Gregory John Casamento <greg_casamento@yahoo.com>
* Date: 2006
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
*/
#ifndef INCLUDED_GormWrapperBuilder_h
#define INCLUDED_GormWrapperBuilder_h
#include <Foundation/NSObject.h>
@class NSFileWrapper, GormDocument, NSString, NSMutableDictionary;
@protocol GormWrapperBuilder
- (NSMutableDictionary *) buildFileWrapperDictionaryWithDocument: (GormDocument *)document;
- (NSFileWrapper *) buildFileWrapperWithDocument: (GormDocument *)document;
@end
@interface GormWrapperBuilder : NSObject <GormWrapperBuilder>
{
GormDocument *document;
}
@end
@interface GormWrapperBuilderFactory : NSObject
+ (GormWrapperBuilderFactory *) sharedWrapperBuilderFactory;
+ (void) registerWrapperBuilderClass: (Class) aClass;
- (id<GormWrapperBuilder>) wrapperBuilderForType: (NSString *) type;
@end
#endif

View file

@ -0,0 +1,165 @@
/* GormWrapperBuilder
*
* These classes handle loading different formats into the
* document's data structures.
*
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* Author: Gregory John Casamento <greg_casamento@yahoo.com>
* Date: 2006
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
*/
#include <AppKit/NSFileWrapper.h>
#include <Foundation/NSString.h>
#include <Foundation/NSDictionary.h>
#include <GormCore/GormWrapperBuilder.h>
#include <GormCore/GormDocument.h>
#include <GormCore/GormPrivate.h>
#include <GormCore/GormSound.h>
#include <GormCore/GormImage.h>
static NSMutableDictionary *_wrapperBuilderMap = nil;
static GormWrapperBuilderFactory *_sharedWrapperBuilderFactory = nil;
@implementation GormWrapperBuilder
+ (NSString *) type
{
[self subclassResponsibility: _cmd];
return nil;
}
- (NSFileWrapper *) buildFileWrapperWithDocument: (GormDocument *)doc
{
return [[NSFileWrapper alloc] initDirectoryWithFileWrappers:
[self buildFileWrapperDictionaryWithDocument: doc]];
}
- (NSMutableDictionary *) buildFileWrapperDictionaryWithDocument: (GormDocument *)doc
{
NSMutableDictionary *fileWrappers = [NSMutableDictionary dictionary];
NSFileWrapper *scmDirWrapper = nil;
// Assign document and don't retain...
document = doc;
//
// Add the SCM wrapper to the wrapper, if it's present.
//
scmDirWrapper = [document scmWrapper];
if(scmDirWrapper != nil)
{
NSString *name = [[scmDirWrapper filename] lastPathComponent];
[fileWrappers setObject: scmDirWrapper forKey: name];
}
//
// Copy resources into the new folder...
// Gorm doesn't copy these into the folder right away since the folder may
// not yet exist. This allows the user to add/delete resources as they see fit
// but only those which they end up with will actually be put into the wrapper
// when the model/document is saved.
//
NSArray *resources = [[document sounds] arrayByAddingObjectsFromArray:
[document images]];
id object = nil;
NSEnumerator *en = [resources objectEnumerator];
while ((object = [en nextObject]) != nil)
{
if([object isSystemResource] == NO)
{
NSString *path = [object path];
NSString *resName = nil;
NSData *resData = nil;
NSFileWrapper *fileWrapper = nil;
if([object isInWrapper])
{
resName = [object filename];
resData = [object data];
}
else
{
resName = [path lastPathComponent];
resData = [NSData dataWithContentsOfFile: path];
[object setData: resData];
[object setInWrapper: YES];
}
fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents: resData];
[fileWrappers setObject: fileWrapper forKey: resName];
RELEASE(fileWrapper);
}
}
return fileWrappers;
}
@end
@implementation GormWrapperBuilderFactory
+ (void) initialize
{
NSArray *classes = GSObjCAllSubclassesOfClass([GormWrapperBuilder class]);
NSEnumerator *en = [classes objectEnumerator];
Class cls = nil;
while((cls = [en nextObject]) != nil)
{
[self registerWrapperBuilderClass: cls];
}
}
+ (void) registerWrapperBuilderClass: (Class)aClass
{
if(_wrapperBuilderMap == nil)
{
_wrapperBuilderMap = [[NSMutableDictionary alloc] initWithCapacity: 5];
}
[_wrapperBuilderMap setObject: aClass forKey: (NSString *)[aClass type]];
}
+ (GormWrapperBuilderFactory *) sharedWrapperBuilderFactory
{
if(_sharedWrapperBuilderFactory == nil)
{
_sharedWrapperBuilderFactory = [[self alloc] init];
}
return _sharedWrapperBuilderFactory;
}
- (id) init
{
if((self = [super init]) != nil)
{
if(_sharedWrapperBuilderFactory == nil)
{
_sharedWrapperBuilderFactory = self;
}
}
return self;
}
- (id<GormWrapperBuilder>) wrapperBuilderForType: (NSString *) type
{
Class cls = [_wrapperBuilderMap objectForKey: type];
id<GormWrapperBuilder> obj = AUTORELEASE([[cls alloc] init]);
return obj;
}
@end

View file

@ -0,0 +1,51 @@
/* GormWrapperLoader
*
* This class is a subclass of the NSDocumentController
*
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* Author: Gregory John Casamento <greg_casamento@yahoo.com>
* Date: 2006
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
*/
#ifndef INCLUDED_GormWrapperLoader_h
#define INCLUDED_GormWrapperLoader_h
#include <Foundation/NSObject.h>
@class NSFileWrapper, GormDocument, NSString;
@protocol GormWrapperLoader
- (BOOL) loadFileWrapper: (NSFileWrapper *)wrapper withDocument: (GormDocument *)document;
@end
@interface GormWrapperLoader : NSObject <GormWrapperLoader>
{
GormDocument *document;
}
- (void) saveSCMDirectory: (NSDictionary *) fileWrappers;
@end
@interface GormWrapperLoaderFactory : NSObject
+ (GormWrapperLoaderFactory *) sharedWrapperLoaderFactory;
+ (void) registerWrapperLoaderClass: (Class) aClass;
- (id<GormWrapperLoader>) wrapperLoaderForType: (NSString *) type;
@end
#endif

View file

@ -0,0 +1,157 @@
/* GormWrapperLoader
*
* These classes handle loading different formats into the
* document's data structures.
*
* Copyright (C) 2006 Free Software Foundation, Inc.
*
* Author: Gregory John Casamento <greg_casamento@yahoo.com>
* Date: 2006
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
*/
#include <AppKit/NSFileWrapper.h>
#include <Foundation/NSString.h>
#include <GormCore/GormWrapperLoader.h>
#include <GormCore/GormDocument.h>
#include <GormCore/GormPrivate.h>
#include <GormCore/GormSound.h>
#include <GormCore/GormImage.h>
static NSMutableDictionary *_wrapperLoaderMap = nil;
static GormWrapperLoaderFactory *_sharedWrapperLoaderFactory = nil;
@implementation GormWrapperLoader
+ (NSString *) type
{
[self subclassResponsibility: _cmd];
return nil;
}
- (void) saveSCMDirectory: (NSDictionary *) fileWrappers
{
[document setSCMWrapper: [fileWrappers objectForKey: @".svn"]];
if([document scmWrapper] == nil)
{
[document setSCMWrapper: [fileWrappers objectForKey: @"CVS"]];
}
}
- (BOOL) loadFileWrapper: (NSFileWrapper *)wrapper withDocument: (GormDocument *)doc
{
if ([wrapper isDirectory])
{
NSDictionary *fileWrappers = nil;
NSString *key = nil;
NSArray *imageFileTypes = [NSImage imageFileTypes];
NSArray *soundFileTypes = [NSSound soundUnfilteredFileTypes];
NSMutableArray *images = [NSMutableArray array];
NSMutableArray *sounds = [NSMutableArray array];
NSData *fileData = nil;
document = doc; // don't retain...
key = nil;
fileWrappers = [wrapper fileWrappers];
[self saveSCMDirectory: fileWrappers];
NSEnumerator *enumerator = [fileWrappers keyEnumerator];
while((key = [enumerator nextObject]) != nil)
{
NSFileWrapper *fw = [fileWrappers objectForKey: key];
if([fw isRegularFile])
{
if ([imageFileTypes containsObject: [key pathExtension]])
{
[images addObject: [GormImage imageForData: fileData
withFileName: key
inWrapper: YES]];
}
else if ([soundFileTypes containsObject: [key pathExtension]])
{
[sounds addObject: [GormSound soundForData: fileData
withFileName: key
inWrapper: YES]];
}
}
}
[document setSounds: sounds];
[document setImages: images];
}
else
{
return NO;
}
return YES;
}
@end
@implementation GormWrapperLoaderFactory
+ (void) initialize
{
NSArray *classes = GSObjCAllSubclassesOfClass([GormWrapperLoader class]);
NSEnumerator *en = [classes objectEnumerator];
Class cls = nil;
while((cls = [en nextObject]) != nil)
{
[self registerWrapperLoaderClass: cls];
}
}
+ (void) registerWrapperLoaderClass: (Class)aClass
{
if(_wrapperLoaderMap == nil)
{
_wrapperLoaderMap = [[NSMutableDictionary alloc] initWithCapacity: 5];
}
[_wrapperLoaderMap setObject: aClass forKey: (NSString *)[aClass type]];
}
+ (GormWrapperLoaderFactory *) sharedWrapperLoaderFactory
{
if(_sharedWrapperLoaderFactory == nil)
{
_sharedWrapperLoaderFactory = [[self alloc] init];
}
return _sharedWrapperLoaderFactory;
}
- (id) init
{
if((self = [super init]) != nil)
{
if(_sharedWrapperLoaderFactory == nil)
{
_sharedWrapperLoaderFactory = self;
}
}
return self;
}
- (id<GormWrapperLoader>) wrapperLoaderForType: (NSString *) type
{
Class cls = [_wrapperLoaderMap objectForKey: type];
id<GormWrapperLoader> obj = AUTORELEASE([[cls alloc] init]);
return obj;
}
@end