2006-06-10 13:34:44 +00:00
|
|
|
/* 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
|
2007-11-05 23:44:36 +00:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2006-06-10 13:34:44 +00:00
|
|
|
* (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
|
2008-01-01 02:24:35 +00:00
|
|
|
{
|
|
|
|
NSMutableArray *_repairLog;
|
|
|
|
id message;
|
|
|
|
id textField;
|
|
|
|
id panel;
|
|
|
|
}
|
2006-06-10 13:34:44 +00:00
|
|
|
@end
|
|
|
|
|
2008-01-03 19:51:16 +00:00
|
|
|
@interface NSWindow (Level)
|
|
|
|
- (int) windowLevel;
|
|
|
|
@end;
|
|
|
|
|
|
|
|
@implementation NSWindow (Level)
|
|
|
|
- (int) windowLevel
|
|
|
|
{
|
|
|
|
return _windowLevel;
|
|
|
|
}
|
|
|
|
@end;
|
|
|
|
|
2006-06-10 13:34:44 +00:00
|
|
|
@implementation GormGormWrapperLoader
|
2008-06-24 23:18:16 +00:00
|
|
|
+ (NSString *) fileType
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
|
|
|
return @"GSGormFileType";
|
|
|
|
}
|
|
|
|
|
2008-01-01 02:24:35 +00:00
|
|
|
- (id) init
|
|
|
|
{
|
|
|
|
if((self = [super init]) != nil)
|
|
|
|
{
|
|
|
|
_repairLog = [[NSMutableArray alloc] init];
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
RELEASE(_repairLog);
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _openMessagePanel: (NSString *) msg
|
|
|
|
{
|
|
|
|
NSEnumerator *en = [_repairLog objectEnumerator];
|
|
|
|
id m = nil;
|
|
|
|
|
|
|
|
if([NSBundle loadNibNamed: @"GormInconsistenciesPanel"
|
|
|
|
owner: self] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"Failed to open message panel...");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[message setStringValue: msg];
|
|
|
|
|
|
|
|
while((m = [en nextObject]) != nil)
|
|
|
|
{
|
|
|
|
[textField insertText: m];
|
|
|
|
}
|
|
|
|
|
|
|
|
[panel orderFront: self];
|
|
|
|
}
|
2008-01-02 03:58:37 +00:00
|
|
|
|
|
|
|
[_repairLog removeAllObjects];
|
2008-01-01 02:24:35 +00:00
|
|
|
}
|
|
|
|
|
2006-06-10 13:34:44 +00:00
|
|
|
/**
|
|
|
|
* 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;
|
2006-10-05 02:39:50 +00:00
|
|
|
int errorCount = 0;
|
|
|
|
NSString *errorMsg = nil;
|
2007-12-20 00:13:14 +00:00
|
|
|
NSArray *connections = [document allConnectors];
|
|
|
|
id con = nil;
|
2006-10-05 02:39:50 +00:00
|
|
|
|
2006-06-10 13:34:44 +00:00
|
|
|
NSRunAlertPanel(_(@"Warning"),
|
|
|
|
_(@"You are running with 'GormRepairFileOnLoad' set to YES."),
|
|
|
|
nil, nil, nil);
|
|
|
|
|
2007-12-20 00:13:14 +00:00
|
|
|
/**
|
|
|
|
* Iterate over all objects in nameTable.
|
|
|
|
*/
|
|
|
|
[document deactivateEditors];
|
2006-06-10 13:34:44 +00:00
|
|
|
while((key = [en nextObject]) != nil)
|
|
|
|
{
|
|
|
|
id obj = [[document nameTable] objectForKey: key];
|
2006-10-05 02:39:50 +00:00
|
|
|
|
2007-12-20 00:13:14 +00:00
|
|
|
/*
|
|
|
|
* Take care of any dangling menus...
|
|
|
|
*/
|
2006-06-10 13:34:44 +00:00
|
|
|
if([obj isKindOfClass: [NSMenu class]] && ![key isEqual: @"NSMenu"])
|
|
|
|
{
|
|
|
|
id sm = [obj supermenu];
|
|
|
|
if(sm == nil)
|
|
|
|
{
|
|
|
|
NSArray *menus = findAll(obj);
|
2008-01-01 02:24:35 +00:00
|
|
|
[_repairLog addObject:
|
|
|
|
[NSString stringWithFormat: @"ERROR ==> Found and removed a dangling menu %@, %@.\n",
|
2008-01-01 19:04:15 +00:00
|
|
|
obj, key]];
|
2006-06-10 13:34:44 +00:00
|
|
|
[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...
|
2006-10-05 02:39:50 +00:00
|
|
|
errorCount++;
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-20 00:13:14 +00:00
|
|
|
/*
|
|
|
|
* Take care of any dangling menu items...
|
|
|
|
*/
|
2008-01-01 19:04:15 +00:00
|
|
|
/*
|
2006-06-10 13:34:44 +00:00
|
|
|
if([obj isKindOfClass: [NSMenuItem class]])
|
|
|
|
{
|
|
|
|
id m = [obj menu];
|
|
|
|
if(m == nil)
|
|
|
|
{
|
|
|
|
id sm = [obj submenu];
|
|
|
|
|
2008-01-01 02:24:35 +00:00
|
|
|
[_repairLog addObject:
|
2008-01-01 19:04:15 +00:00
|
|
|
[NSString stringWithFormat: @"ERROR ==> Found and removed an unattached menu item %@, %@.\n",
|
|
|
|
obj, key]];
|
2006-06-10 13:34:44 +00:00
|
|
|
[document detachObject: obj];
|
|
|
|
|
|
|
|
// if there are any submenus, detach those as well.
|
|
|
|
if(sm != nil)
|
|
|
|
{
|
|
|
|
NSArray *menus = findAll(sm);
|
|
|
|
[document detachObjects: menus];
|
|
|
|
}
|
2006-10-05 02:39:50 +00:00
|
|
|
errorCount++;
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
|
|
|
}
|
2008-01-01 19:04:15 +00:00
|
|
|
*/
|
2006-06-10 13:34:44 +00:00
|
|
|
|
2007-12-20 00:13:14 +00:00
|
|
|
/*
|
2006-10-05 02:39:50 +00:00
|
|
|
* If there is a view which is not associated with a name, give it one...
|
|
|
|
*/
|
|
|
|
if([obj isKindOfClass: [NSWindow class]])
|
|
|
|
{
|
|
|
|
NSArray *allViews = allSubviews([obj contentView]);
|
|
|
|
NSEnumerator *ven = [allViews objectEnumerator];
|
|
|
|
id v = nil;
|
2008-01-03 19:51:16 +00:00
|
|
|
|
|
|
|
if([obj windowLevel] != NSNormalWindowLevel)
|
|
|
|
{
|
|
|
|
[obj setLevel: NSNormalWindowLevel];
|
|
|
|
[_repairLog addObject:
|
|
|
|
[NSString stringWithFormat:
|
|
|
|
@"ERROR ==> Found window %@ with an invalid level, correcting.\n",
|
|
|
|
obj]];
|
|
|
|
errorCount++;
|
|
|
|
}
|
2006-10-05 02:39:50 +00:00
|
|
|
|
|
|
|
while((v = [ven nextObject]) != nil)
|
|
|
|
{
|
2007-12-20 00:13:14 +00:00
|
|
|
NSString *name = nil;
|
2008-01-01 19:04:15 +00:00
|
|
|
|
|
|
|
// skip these...
|
|
|
|
if([v isKindOfClass: [NSMatrix class]])
|
|
|
|
{
|
|
|
|
[_repairLog addObject: @"INFO: Skipping NSMatrix view.\n"];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if([v isKindOfClass: [NSScroller class]] &&
|
|
|
|
[[v superview] isKindOfClass: [NSTextView class]])
|
|
|
|
{
|
|
|
|
[_repairLog addObject: @"INFO: Skipping NSScroller in an NSTextView.\n"];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if([v isKindOfClass: [NSScroller class]] &&
|
|
|
|
[[v superview] isKindOfClass: [NSBrowser class]])
|
|
|
|
{
|
|
|
|
[_repairLog addObject: @"INFO: Skipping NSScroller in an NSTextView.\n"];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if([v isKindOfClass: [NSClipView class]] &&
|
|
|
|
[[v superview] isKindOfClass: [NSTextView class]])
|
|
|
|
{
|
|
|
|
[_repairLog addObject: @"INFO: Skipping NSClipView in an NSTextView.\n"];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if([v isKindOfClass: [NSClipView class]] &&
|
|
|
|
[[v superview] isKindOfClass: [NSBrowser class]])
|
|
|
|
{
|
|
|
|
[_repairLog addObject: @"INFO: Skipping NSClipView in an NSTextView.\n"];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2007-12-20 00:13:14 +00:00
|
|
|
if((name = [document nameForObject: v]) == nil)
|
2006-10-05 02:39:50 +00:00
|
|
|
{
|
|
|
|
[document attachObject: v toParent: [v superview]];
|
|
|
|
name = [document nameForObject: v];
|
2008-01-01 02:24:35 +00:00
|
|
|
[_repairLog addObject:
|
|
|
|
[NSString stringWithFormat:
|
|
|
|
@"ERROR ==> Found view %@ without an associated name, adding to the nametable as %@\n",
|
|
|
|
v, name]];
|
2006-10-05 02:39:50 +00:00
|
|
|
if([v respondsToSelector: @selector(stringValue)])
|
|
|
|
{
|
2008-01-01 02:24:35 +00:00
|
|
|
[_repairLog addObject: [NSString stringWithFormat: @"INFO: View string value is %@\n",[v stringValue]]];
|
2006-10-05 02:39:50 +00:00
|
|
|
}
|
|
|
|
errorCount++;
|
|
|
|
}
|
2008-01-01 02:24:35 +00:00
|
|
|
[_repairLog addObject: [NSString stringWithFormat: @"INFO: Checking view %@ with name %@\n", v, name]];
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-20 00:13:14 +00:00
|
|
|
[document reactivateEditors];
|
|
|
|
|
|
|
|
/**
|
2008-01-01 02:24:35 +00:00
|
|
|
* Iterate over all connections... remove connections with nil sources.
|
2007-12-20 00:13:14 +00:00
|
|
|
*/
|
|
|
|
en = [connections objectEnumerator];
|
|
|
|
while((con = [en nextObject]) != nil)
|
|
|
|
{
|
2008-01-03 19:51:16 +00:00
|
|
|
id src = [con source];
|
|
|
|
id dst = [con destination];
|
2007-12-20 00:13:14 +00:00
|
|
|
if([con isKindOfClass: [NSNibConnector class]])
|
|
|
|
{
|
2008-01-03 19:51:16 +00:00
|
|
|
if(src == nil)
|
2007-12-20 00:13:14 +00:00
|
|
|
{
|
2008-01-01 02:24:35 +00:00
|
|
|
[_repairLog addObject:
|
|
|
|
[NSString stringWithFormat: @"ERROR ==> Removing bad connector with nil source: %@\n",con]];
|
2007-12-20 00:13:14 +00:00
|
|
|
[document removeConnector: con];
|
|
|
|
errorCount++;
|
|
|
|
}
|
2008-01-03 19:51:16 +00:00
|
|
|
else if([src isKindOfClass: [NSString class]])
|
|
|
|
{
|
|
|
|
id obj = [document objectForName: src];
|
|
|
|
if(obj == nil)
|
|
|
|
{
|
|
|
|
[_repairLog addObject:
|
|
|
|
[NSString stringWithFormat:
|
|
|
|
@"ERROR ==> Removing bad connector with source that is not in the nametable: %@\n",
|
|
|
|
con]];
|
|
|
|
[document removeConnector: con];
|
|
|
|
errorCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if([dst isKindOfClass: [NSString class]])
|
|
|
|
{
|
|
|
|
id obj = [document objectForName: dst];
|
|
|
|
if(obj == nil)
|
|
|
|
{
|
|
|
|
[_repairLog addObject:
|
|
|
|
[NSString stringWithFormat:
|
|
|
|
@"ERROR ==> Removing bad connector with destination that is not in the nametable: %@\n",
|
|
|
|
con]];
|
|
|
|
[document removeConnector: con];
|
|
|
|
errorCount++;
|
|
|
|
}
|
|
|
|
}
|
2007-12-20 00:13:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-05 02:39:50 +00:00
|
|
|
// report the number of errors...
|
|
|
|
if(errorCount > 0)
|
|
|
|
{
|
|
|
|
errorMsg = [NSString stringWithFormat: @"%d inconsistencies were found, please save the file.",errorCount];
|
2008-01-01 02:24:35 +00:00
|
|
|
[self _openMessagePanel: errorMsg];
|
2008-01-02 04:08:05 +00:00
|
|
|
[document touch];
|
2006-10-05 02:39:50 +00:00
|
|
|
}
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
BOOL result = NO;
|
|
|
|
|
2006-06-10 13:34:44 +00:00
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
NSData *data = nil;
|
|
|
|
NSData *classes = nil;
|
|
|
|
NSUnarchiver *u = nil;
|
|
|
|
NSEnumerator *enumerator = nil;
|
|
|
|
id <IBConnectors> con = nil;
|
|
|
|
NSString *ownerClass, *key = nil;
|
2006-08-20 16:25:23 +00:00
|
|
|
BOOL repairFile = [[NSUserDefaults standardUserDefaults]
|
|
|
|
boolForKey: @"GormRepairFileOnLoad"];
|
2006-06-10 13:34:44 +00:00
|
|
|
GormPalettesManager *palettesManager = [(id<Gorm>)NSApp palettesManager];
|
|
|
|
NSDictionary *substituteClasses = [palettesManager substituteClasses];
|
|
|
|
NSEnumerator *en = [substituteClasses keyEnumerator];
|
|
|
|
NSString *subClassName = nil;
|
2012-04-20 06:12:32 +00:00
|
|
|
NSUInteger version = NSNotFound;
|
2006-06-10 13:34:44 +00:00
|
|
|
NSDictionary *fileWrappers = nil;
|
2008-01-05 19:03:45 +00:00
|
|
|
GSNibContainer *container;
|
|
|
|
NSArray *visible;
|
|
|
|
NSArray *deferred;
|
|
|
|
GormFilesOwner *filesOwner;
|
|
|
|
GormFirstResponder *firstResponder;
|
|
|
|
NSArray *objs;
|
|
|
|
NSMutableArray *connections;
|
|
|
|
NSDictionary *nt;
|
2008-01-05 22:28:49 +00:00
|
|
|
id visObj;
|
|
|
|
id defObj;
|
2006-08-20 16:25:23 +00:00
|
|
|
|
2006-06-10 13:34:44 +00:00
|
|
|
if ([super loadFileWrapper: wrapper withDocument: doc])
|
|
|
|
{
|
|
|
|
GormClassManager *classManager = [document classManager];
|
|
|
|
|
|
|
|
key = nil;
|
2009-03-20 03:40:53 +00:00
|
|
|
if ([wrapper isDirectory])
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
fileWrappers = [wrapper fileWrappers];
|
|
|
|
|
|
|
|
enumerator = [fileWrappers keyEnumerator];
|
|
|
|
while((key = [enumerator nextObject]) != nil)
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
NSFileWrapper *fw = [fileWrappers objectForKey: key];
|
|
|
|
if([fw isRegularFile])
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
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"])
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
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);
|
|
|
|
}
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-03-20 03:40:53 +00:00
|
|
|
else if ([wrapper isRegularFile]) // if it's a file... here we need to handle legacy files.
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
NSString *classesFileName = [[[document documentPath] stringByDeletingPathExtension]
|
|
|
|
stringByAppendingPathExtension: @"classes"];
|
2006-06-14 05:47:54 +00:00
|
|
|
|
2009-03-20 03:40:53 +00:00
|
|
|
// dump the contents to the data section...
|
|
|
|
data = [wrapper regularFileContents];
|
|
|
|
classes = [NSData dataWithContentsOfFile: classesFileName];
|
2006-06-14 05:47:54 +00:00
|
|
|
|
2009-03-20 03:40:53 +00:00
|
|
|
// load the custom classes...
|
|
|
|
if (![classManager loadCustomClassesWithData: classes])
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
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);
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-20 03:40:53 +00:00
|
|
|
// check the data...
|
|
|
|
if (data == nil || classes == nil)
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
result = NO;
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
2009-03-20 03:40:53 +00:00
|
|
|
else
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
/*
|
|
|
|
* 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)
|
2006-06-10 13:34:44 +00:00
|
|
|
{
|
2009-03-20 03:40:53 +00:00
|
|
|
NSString *realClassName = [substituteClasses objectForKey: subClassName];
|
|
|
|
[u decodeClassName: realClassName
|
|
|
|
asClassName: subClassName];
|
|
|
|
}
|
|
|
|
|
|
|
|
// turn off custom classes.
|
|
|
|
[GSClassSwapper setIsInInterfaceBuilder: YES];
|
|
|
|
container = [u decodeObject];
|
|
|
|
if (container == nil || [container isKindOfClass: [GSNibContainer class]] == NO)
|
|
|
|
{
|
|
|
|
result = NO;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// turn on custom classes.
|
|
|
|
[GSClassSwapper setIsInInterfaceBuilder: NO];
|
|
|
|
|
|
|
|
//
|
|
|
|
// Retrieve the custom class data and refresh the classes view...
|
|
|
|
//
|
|
|
|
[classManager setCustomClassMap:
|
|
|
|
[NSMutableDictionary dictionaryWithDictionary:
|
|
|
|
[container customClasses]]];
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get all of the visible objects...
|
|
|
|
//
|
|
|
|
visible = [container visibleWindows];
|
|
|
|
visObj = nil;
|
|
|
|
enumerator = [visible objectEnumerator];
|
|
|
|
while((visObj = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
[document setObject: visObj isVisibleAtLaunch: YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get all of the deferred objects...
|
|
|
|
//
|
|
|
|
deferred = [container deferredWindows];
|
|
|
|
defObj = nil;
|
|
|
|
enumerator = [deferred objectEnumerator];
|
|
|
|
while((defObj = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
[document setObject: defObj isDeferred: YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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'.
|
|
|
|
//
|
|
|
|
filesOwner = [document filesOwner];
|
|
|
|
firstResponder = [document firstResponder];
|
|
|
|
ownerClass = [[container nameTable] objectForKey: @"NSOwner"];
|
|
|
|
if (ownerClass)
|
|
|
|
{
|
|
|
|
[filesOwner setClassName: ownerClass];
|
|
|
|
}
|
|
|
|
[[container nameTable] setObject: filesOwner forKey: @"NSOwner"];
|
|
|
|
[[container nameTable] setObject: firstResponder forKey: @"NSFirst"];
|
|
|
|
|
|
|
|
//
|
|
|
|
// Add entries...
|
|
|
|
//
|
|
|
|
[[document nameTable] addEntriesFromDictionary: [container nameTable]];
|
|
|
|
|
|
|
|
//
|
|
|
|
// Add top level items...
|
|
|
|
//
|
|
|
|
objs = [[container topLevelObjects] allObjects];
|
|
|
|
[[document topLevelObjects] addObjectsFromArray: objs];
|
|
|
|
|
|
|
|
//
|
|
|
|
// Add connections
|
|
|
|
//
|
|
|
|
connections = [document connections];
|
|
|
|
[connections addObjectsFromArray: [container connections]];
|
|
|
|
|
|
|
|
/* Iterate over the contents of nameTable and create the connections */
|
|
|
|
nt = [document nameTable];
|
|
|
|
enumerator = [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.
|
|
|
|
*/
|
|
|
|
version = [u versionForClassName: NSStringFromClass([GSNibContainer class])];
|
|
|
|
if(version == 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];
|
|
|
|
}
|
|
|
|
else if(version == 1)
|
|
|
|
{
|
|
|
|
// nothing else, just mark it as older...
|
|
|
|
[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];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Rebuild the mapping from object to name for the nameTable...
|
|
|
|
*/
|
|
|
|
[document rebuildObjToNameMapping];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Repair the .gorm file, if needed.
|
|
|
|
*/
|
|
|
|
if(repairFile)
|
|
|
|
{
|
|
|
|
[self _repairFile];
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
// done...
|
|
|
|
result = YES;
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
NSRunAlertPanel(_(@"Problem Loading"),
|
|
|
|
[NSString stringWithFormat: @"Failed to load file. Exception: %@",[localException reason]],
|
|
|
|
_(@"OK"), nil, nil);
|
2009-03-20 03:40:53 +00:00
|
|
|
result = NO;
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
|
|
|
NS_ENDHANDLER;
|
|
|
|
|
|
|
|
// if we made it here, then it was a success....
|
2009-03-20 03:40:53 +00:00
|
|
|
return result;
|
2006-06-10 13:34:44 +00:00
|
|
|
}
|
|
|
|
@end
|