1999-12-08 15:04:57 +00:00
/ * GormDocument . m
*
2005-04-11 20:42:33 +00:00
* This class contains Gorm specific implementation of the IBDocuments
* protocol plus additional methods which are useful for managing the
* contents of the document .
1999-12-08 15:04:57 +00:00
*
2005-04-11 20:42:33 +00:00
* Copyright ( C ) 1999 , 2002 , 2003 , 2004 , 2005 Free Software Foundation , Inc .
*
* Author : Gregory John Casamento < greg_casamento @ yahoo . com >
* Date : 2002 , 2003 , 2004 , 2005
1999-12-08 15:04:57 +00:00
* Author : Richard Frith - Macdonald < richard @ brainstrom . co . uk >
* Date : 1999
2002-11-23 22:52:27 +00:00
*
1999-12-08 15:04:57 +00:00
* 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
2005-05-26 03:37:38 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02111 USA .
1999-12-08 15:04:57 +00:00
* /
# include "GormPrivate.h"
2001-10-05 15:02:55 +00:00
# include "GormClassManager.h"
# include "GormCustomView.h"
2002-07-08 04:45:23 +00:00
# include "GormOutlineView.h"
2004-07-12 04:16:09 +00:00
# include "GormFunctions.h"
# include "GormFilePrefsManager.h"
2004-07-27 06:20:45 +00:00
# include "GormViewWindow.h"
2004-07-12 04:16:09 +00:00
# include < Foundation / NSUserDefaults . h >
2004-11-27 22:38:53 +00:00
# include < Foundation / NSException . h >
2002-11-18 20:54:26 +00:00
# include < AppKit / NSImage . h >
2002-11-04 13:52:31 +00:00
# include < AppKit / NSSound . h >
2003-05-23 02:25:34 +00:00
# include < AppKit / NSNibConnector . h >
2004-05-20 02:34:03 +00:00
# include < AppKit / NSNibLoading . h >
2004-07-12 04:16:09 +00:00
# include < GNUstepGUI / GSNibTemplates . h >
2004-11-18 05:34:19 +00:00
# include "NSView+GormExtensions.h"
2004-12-05 20:52:36 +00:00
# include "GormSound.h"
# include "GormImage.h"
2005-04-22 00:43:10 +00:00
# include "GormViewResourceManager.h"
2005-04-23 17:16:10 +00:00
# include "GormClassEditor.h"
2005-04-23 18:43:36 +00:00
# include "GormSoundEditor.h"
# include "GormImageEditor.h"
# include "GormObjectEditor.h"
1999-12-08 15:04:57 +00:00
2004-07-27 06:20:45 +00:00
@ interface GormDisplayCell : NSButtonCell
2003-04-18 05:40:25 +00:00
@ end
2003-10-08 05:00:21 +00:00
2003-04-18 05:40:25 +00:00
@ implementation GormDisplayCell
- ( void ) setShowsFirstResponder : ( BOOL ) flag
{
[ super setShowsFirstResponder : NO ] ; // Never show ugly frame round button
}
@ end
2004-06-26 12:19:18 +00:00
@ interface NSNibConnector ( GormExtension )
2004-01-06 06:11:24 +00:00
- ( BOOL ) isEqual : ( id ) object ;
@ end
2004-06-26 12:19:18 +00:00
@ implementation NSNibConnector ( GormExtension )
2004-01-06 06:11:24 +00:00
- ( BOOL ) isEqual : ( id ) object
{
BOOL result = NO ;
2004-06-26 22:08:42 +00:00
if ( self = = object )
{
result = YES ;
}
else if ( [ [ self source ] isEqual : [ object source ] ] &&
2004-01-06 06:11:24 +00:00
[ [ self destination ] isEqual : [ object destination ] ] &&
2004-06-26 12:19:18 +00:00
[ [ self label ] isEqual : [ object label ] ] &&
( [ self class ] = = [ object class ] ) )
2004-01-06 06:11:24 +00:00
{
result = YES ;
}
return result ;
}
@ end
2002-12-22 00:33:44 +00:00
// Internal only
NSString * GSCustomClassMap = @ "GSCustomClassMap" ;
2002-11-13 16:10:22 +00:00
@ interface GormDocument ( GModel )
- ( id ) openGModel : ( NSString * ) path ;
2002-11-05 05:42:45 +00:00
@ end
1999-12-13 17:01:35 +00:00
@ implementation GormFirstResponder
- ( NSImage * ) imageForViewer
{
static NSImage * image = nil ;
if ( image = = nil )
{
NSBundle * bundle = [ NSBundle mainBundle ] ;
NSString * path = [ bundle pathForImageResource : @ "GormFirstResponder" ] ;
image = [ [ NSImage alloc ] initWithContentsOfFile : path ] ;
}
return image ;
}
1999-12-21 11:38:49 +00:00
- ( NSString * ) inspectorClassName
{
1999-12-21 16:48:32 +00:00
return @ "GormNotApplicableInspector" ;
}
- ( NSString * ) connectInspectorClassName
{
2004-05-31 03:03:07 +00:00
return @ "GormNotApplicableInspector" ;
1999-12-21 16:48:32 +00:00
}
- ( NSString * ) sizeInspectorClassName
{
return @ "GormNotApplicableInspector" ;
1999-12-21 11:38:49 +00:00
}
2002-11-24 05:52:50 +00:00
- ( NSString * ) classInspectorClassName
{
return @ "GormNotApplicableInspector" ;
}
2004-03-04 04:01:09 +00:00
- ( NSString * ) className
{
return @ "FirstResponder" ;
}
1999-12-13 17:01:35 +00:00
@ end
1999-12-08 15:04:57 +00:00
1999-12-14 17:38:17 +00:00
/ *
* Trivial classes for connections from objects to their editors , and from
* child editors to their parents . This does nothing special , but we can
* use the fact that it ' s a different class to search for it in the connections
* array .
* /
@ interface GormObjectToEditor : NSNibConnector
@ end
@ implementation GormObjectToEditor
@ end
@ interface GormEditorToParent : NSNibConnector
@ end
@ implementation GormEditorToParent
@ end
1999-12-08 15:04:57 +00:00
@ implementation GormDocument
1999-12-14 19:55:18 +00:00
static NSImage * objectsImage = nil ;
static NSImage * imagesImage = nil ;
static NSImage * soundsImage = nil ;
static NSImage * classesImage = nil ;
2004-07-12 04:16:09 +00:00
static NSImage * fileImage = nil ;
1999-12-14 19:55:18 +00:00
2005-04-11 20:42:33 +00:00
/ * *
* Initialize the class .
* /
1999-12-14 17:38:17 +00:00
+ ( void ) initialize
{
if ( self = = [ GormDocument class ] )
{
1999-12-14 19:55:18 +00:00
NSBundle * bundle ;
NSString * path ;
bundle = [ NSBundle mainBundle ] ;
path = [ bundle pathForImageResource : @ "GormObject" ] ;
if ( path ! = nil )
{
objectsImage = [ [ NSImage alloc ] initWithContentsOfFile : path ] ;
}
path = [ bundle pathForImageResource : @ "GormImage" ] ;
if ( path ! = nil )
{
imagesImage = [ [ NSImage alloc ] initWithContentsOfFile : path ] ;
}
path = [ bundle pathForImageResource : @ "GormSound" ] ;
if ( path ! = nil )
{
soundsImage = [ [ NSImage alloc ] initWithContentsOfFile : path ] ;
}
path = [ bundle pathForImageResource : @ "GormClass" ] ;
if ( path ! = nil )
{
classesImage = [ [ NSImage alloc ] initWithContentsOfFile : path ] ;
}
2004-07-12 04:16:09 +00:00
path = [ bundle pathForImageResource : @ "Gorm" ] ;
if ( path ! = nil )
{
fileImage = [ [ NSImage alloc ] initWithContentsOfFile : path ] ;
}
2005-04-11 04:05:30 +00:00
2005-04-22 00:43:10 +00:00
// register the resource managers . . .
2005-04-11 04:05:30 +00:00
[ IBResourceManager registerResourceManagerClass : [ IBResourceManager class ] ] ;
2005-04-22 00:43:10 +00:00
[ IBResourceManager registerResourceManagerClass : [ GormViewResourceManager class ] ] ;
2002-11-18 06:15:06 +00:00
[ self setVersion : GNUSTEP_NIB _VERSION ] ;
1999-12-14 17:38:17 +00:00
}
}
2005-04-11 20:42:33 +00:00
/ * *
* Initialize the new GormDocument object .
* /
2004-05-19 01:36:37 +00:00
- ( id ) init
1999-12-08 15:04:57 +00:00
{
2004-05-19 01:36:37 +00:00
self = [ super init ] ;
if ( self ! = nil )
1999-12-08 15:04:57 +00:00
{
2004-05-20 02:34:03 +00:00
if ( [ NSBundle loadNibNamed : @ "GormDocument" owner : self ] )
{
NSNotificationCenter * nc = [ NSNotificationCenter defaultCenter ] ;
NSRect scrollRect = { { 0 , 0 } , { 340 , 188 } } ;
NSRect mainRect = { { 20 , 0 } , { 320 , 188 } } ;
NSUserDefaults * defaults = [ NSUserDefaults standardUserDefaults ] ;
2004-11-13 05:06:15 +00:00
// initialize . . .
2005-06-17 04:41:24 +00:00
openEditors = [ [ NSMutableArray alloc ] init ] ;
2004-11-18 05:34:19 +00:00
classManager = [ ( GormClassManager * ) [ GormClassManager alloc ] initWithDocument : self ] ;
2004-05-20 02:34:03 +00:00
/ *
* NB . We must retain the map values ( object names ) as the nameTable
* may not hold identical name objects , but merely equal strings .
* /
objToName = NSCreateMapTableWithZone ( NSObjectMapKeyCallBacks ,
NSObjectMapValueCallBacks , 128 , [ self zone ] ) ;
// for saving the editors when the gorm file is persisted .
2005-06-17 04:41:24 +00:00
savedEditors = [ [ NSMutableArray alloc ] init ] ;
2004-05-20 02:34:03 +00:00
[ window setMinSize : [ window frame ] . size ] ;
[ window setTitle : _ ( @ "UNTITLED" ) ] ;
// observe certain notifications . . .
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : NSWindowWillCloseNotification
object : window ] ;
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : NSWindowDidBecomeKeyNotification
object : window ] ;
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : NSWindowWillMiniaturizeNotification
object : window ] ;
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : NSWindowDidDeminiaturizeNotification
object : window ] ;
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : IBClassNameChangedNotification
object : classManager ] ;
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : IBInspectorDidModifyObjectNotification
object : classManager ] ;
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : GormDidModifyClassNotification
object : classManager ] ;
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : GormDidAddClassNotification
object : classManager ] ;
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : IBWillBeginTestingInterfaceNotification
object : nil ] ;
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : IBWillEndTestingInterfaceNotification
object : nil ] ;
2005-04-10 22:21:59 +00:00
[ nc addObserver : self
selector : @ selector ( handleNotification : )
name : IBResourceManagerRegistryDidChangeNotification
object : nil ] ;
2005-04-11 04:05:30 +00:00
// load resource managers
[ self createResourceManagers ] ;
2004-05-20 02:34:03 +00:00
// objects . . .
mainRect . origin = NSMakePoint ( 0 , 0 ) ;
scrollView = [ [ NSScrollView alloc ] initWithFrame : scrollRect ] ;
[ scrollView setHasVerticalScroller : YES ] ;
[ scrollView setHasHorizontalScroller : YES ] ;
[ scrollView setAutoresizingMask :
NSViewHeightSizable | NSViewWidthSizable ] ;
[ scrollView setBorderType : NSBezelBorder ] ;
objectsView = [ [ GormObjectEditor alloc ] initWithObject : nil
2004-05-19 01:36:37 +00:00
inDocument : self ] ;
2004-05-20 02:34:03 +00:00
[ objectsView setFrame : mainRect ] ;
[ objectsView setAutoresizingMask :
NSViewHeightSizable | NSViewWidthSizable ] ;
[ scrollView setDocumentView : objectsView ] ;
RELEASE ( objectsView ) ;
2004-11-09 13:52:27 +00:00
2004-05-20 02:34:03 +00:00
// images . . .
mainRect . origin = NSMakePoint ( 0 , 0 ) ;
imagesScrollView = [ [ NSScrollView alloc ] initWithFrame : scrollRect ] ;
[ imagesScrollView setHasVerticalScroller : YES ] ;
[ imagesScrollView setHasHorizontalScroller : YES ] ;
[ imagesScrollView setAutoresizingMask :
NSViewHeightSizable | NSViewWidthSizable ] ;
[ imagesScrollView setBorderType : NSBezelBorder ] ;
imagesView = [ [ GormImageEditor alloc ] initWithObject : nil
2004-05-19 01:36:37 +00:00
inDocument : self ] ;
2004-05-20 02:34:03 +00:00
[ imagesView setFrame : mainRect ] ;
[ imagesView setAutoresizingMask : NSViewHeightSizable | NSViewWidthSizable ] ;
[ imagesScrollView setDocumentView : imagesView ] ;
RELEASE ( imagesView ) ;
2004-11-09 13:52:27 +00:00
2004-05-20 02:34:03 +00:00
// sounds . . .
mainRect . origin = NSMakePoint ( 0 , 0 ) ;
soundsScrollView = [ [ NSScrollView alloc ] initWithFrame : scrollRect ] ;
[ soundsScrollView setHasVerticalScroller : YES ] ;
[ soundsScrollView setHasHorizontalScroller : YES ] ;
[ soundsScrollView setAutoresizingMask :
NSViewHeightSizable | NSViewWidthSizable ] ;
[ soundsScrollView setBorderType : NSBezelBorder ] ;
soundsView = [ [ GormSoundEditor alloc ] initWithObject : nil
2004-05-19 01:36:37 +00:00
inDocument : self ] ;
2004-05-20 02:34:03 +00:00
[ soundsView setFrame : mainRect ] ;
[ soundsView setAutoresizingMask : NSViewHeightSizable | NSViewWidthSizable ] ;
[ soundsScrollView setDocumentView : soundsView ] ;
RELEASE ( soundsView ) ;
2004-11-09 13:52:27 +00:00
2004-05-20 02:34:03 +00:00
// classes . . .
2005-05-04 09:34:49 +00:00
// classesScrollView = [ [ NSScrollView alloc ] initWithFrame : scrollRect ] ;
// [ classesScrollView setHasVerticalScroller : YES ] ;
// [ classesScrollView setHasHorizontalScroller : NO ] ;
// [ classesScrollView setAutoresizingMask :
// NSViewHeightSizable | NSViewWidthSizable ] ;
// [ classesScrollView setBorderType : NSBezelBorder ] ;
2004-05-20 02:34:03 +00:00
mainRect . origin = NSMakePoint ( 0 , 0 ) ;
2004-11-18 05:34:19 +00:00
classesView = [ ( GormClassEditor * ) [ GormClassEditor alloc ] initWithDocument : self ] ;
2004-08-11 11:16:35 +00:00
[ classesView setFrame : mainRect ] ;
2005-05-04 09:34:49 +00:00
// [ classesScrollView setDocumentView : classesView ] ;
// RELEASE ( classesView ) ;
2004-05-20 02:34:03 +00:00
2004-08-11 11:16:35 +00:00
/ *
* Set the objects view as the initial view the user ' s see on startup .
* /
2005-05-21 17:17:00 +00:00
// [ selectionBox setContentViewMargins : NSZeroSize ] ;
2004-05-20 02:34:03 +00:00
[ selectionBox setContentView : scrollView ] ;
/ *
* Set up special - case dummy objects and add them to the objects view .
* /
2005-06-17 04:41:24 +00:00
filesOwner = [ [ GormFilesOwner alloc ] init ] ;
2004-05-20 02:34:03 +00:00
[ self setName : @ "NSOwner" forObject : filesOwner ] ;
[ objectsView addObject : filesOwner ] ;
2005-06-17 04:41:24 +00:00
firstResponder = [ [ GormFirstResponder alloc ] init ] ;
2004-05-20 02:34:03 +00:00
[ self setName : @ "NSFirst" forObject : firstResponder ] ;
[ objectsView addObject : firstResponder ] ;
/ *
* Set image for this miniwindow .
* /
2004-07-12 04:16:09 +00:00
[ window setMiniwindowImage : [ ( id ) filesOwner imageForViewer ] ] ;
2005-06-17 04:41:24 +00:00
hidden = [ [ NSMutableArray alloc ] init ] ;
2004-05-20 02:34:03 +00:00
2004-07-12 04:16:09 +00:00
// retain the file prefs view . . .
RETAIN ( filePrefsView ) ;
2004-05-20 02:34:03 +00:00
// preload headers . . .
if ( [ defaults boolForKey : @ "PreloadHeaders" ] )
2004-05-19 01:36:37 +00:00
{
2004-05-20 02:34:03 +00:00
NSArray * headerList = [ defaults arrayForKey : @ "HeaderList" ] ;
NSEnumerator * en = [ headerList objectEnumerator ] ;
id obj = nil ;
while ( ( obj = [ en nextObject ] ) ! = nil )
{
2004-12-28 02:25:18 +00:00
NSString * header = ( NSString * ) obj ;
NSDebugLog ( @ "Preloading %@" , header ) ;
NS_DURING
{
if ( ! [ classManager parseHeader : header ] )
{
NSString * file = [ header lastPathComponent ] ;
NSString * message = [ NSString stringWithFormat :
_ ( @ "Unable to parse class in %@" ) , file ] ;
NSRunAlertPanel ( _ ( @ "Problem parsing class" ) ,
message ,
nil , nil , nil ) ;
}
}
NS_HANDLER
{
NSString * message = [ localException reason ] ;
NSRunAlertPanel ( _ ( @ "Problem parsing class" ) ,
message ,
nil , nil , nil ) ;
}
NS_ENDHANDLER ;
2004-05-20 02:34:03 +00:00
}
2004-05-19 01:36:37 +00:00
}
2004-07-01 00:53:42 +00:00
// are we upgrading an archive ?
2004-07-12 04:16:09 +00:00
isOlderArchive = NO ;
2005-04-10 22:21:59 +00:00
2004-08-08 17:23:17 +00:00
// document is open . . .
isDocumentOpen = YES ;
2004-01-06 06:11:24 +00:00
}
2004-05-20 02:34:03 +00:00
else
{
NSLog ( @ "Couldn't load GormDocument interface." ) ;
[ NSApp terminate : self ] ;
}
2004-01-06 06:11:24 +00:00
}
2004-05-19 01:36:37 +00:00
return self ;
1999-12-08 15:04:57 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Perform any additional setup which needs to happen .
* /
2004-05-20 02:34:03 +00:00
- ( void ) awakeFromNib
{
// set up the toolbar . . .
2004-11-18 05:34:19 +00:00
toolbar = [ ( NSToolbar * ) [ NSToolbar alloc ] initWithIdentifier : @ "GormToolbar" ] ;
2004-05-20 02:34:03 +00:00
[ toolbar setAllowsUserCustomization : NO ] ;
[ toolbar setDelegate : self ] ;
2004-07-21 01:49:07 +00:00
[ window setToolbar : toolbar ] ;
RELEASE ( toolbar ) ;
2004-05-25 02:22:00 +00:00
[ toolbar setUsesStandardBackgroundColor : YES ] ;
2004-05-20 02:34:03 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Add aConnector to the set of connectors in this document .
* /
2004-05-19 01:36:37 +00:00
- ( void ) addConnector : ( id < IBConnectors > ) aConnector
1999-12-08 15:04:57 +00:00
{
2004-05-19 01:36:37 +00:00
if ( [ connections indexOfObjectIdenticalTo : aConnector ] = = NSNotFound )
1999-12-08 15:04:57 +00:00
{
2004-05-19 01:36:37 +00:00
NSNotificationCenter * nc = [ NSNotificationCenter defaultCenter ] ;
[ nc postNotificationName : IBWillAddConnectorNotification
object : aConnector ] ;
[ connections addObject : aConnector ] ;
[ nc postNotificationName : IBDidAddConnectorNotification
object : aConnector ] ;
1999-12-08 15:04:57 +00:00
}
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns all connectors .
* /
2004-05-19 01:36:37 +00:00
- ( NSArray * ) allConnectors
2002-11-04 13:52:31 +00:00
{
2004-05-19 01:36:37 +00:00
return [ NSArray arrayWithArray : connections ] ;
2002-11-04 13:52:31 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Creates the proxy font manager .
* /
2004-05-19 01:36:37 +00:00
- ( void ) _instantiateFontManager
2002-11-18 20:54:26 +00:00
{
2004-05-19 01:36:37 +00:00
GSNibItem * item = nil ;
item = [ [ GormObjectProxy alloc ] initWithClassName : @ "NSFontManager"
frame : NSMakeRect ( 0 , 0 , 0 , 0 ) ] ;
[ self setName : @ "NSFont" forObject : item ] ;
[ self attachObject : item toParent : nil ] ;
RELEASE ( item ) ;
// set the holder in the document .
fontManager = ( GormObjectProxy * ) item ;
2004-05-20 02:34:03 +00:00
// [ selectionView selectCellWithTag : 0 ] ;
2004-05-19 01:36:37 +00:00
[ selectionBox setContentView : scrollView ] ;
2002-11-18 20:54:26 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Attach anObject to the document with aParent .
* /
2004-05-19 01:36:37 +00:00
- ( void ) attachObject : ( id ) anObject toParent : ( id ) aParent
2000-01-03 11:00:14 +00:00
{
2004-05-19 01:36:37 +00:00
NSArray * old ;
BOOL newObject = NO ;
2000-01-03 11:00:14 +00:00
/ *
2004-05-19 01:36:37 +00:00
* Create a connector that links this object to its parent .
* A nil parent is the root of the hierarchy so we use a dummy object for it .
2000-01-03 11:00:14 +00:00
* /
2004-05-19 01:36:37 +00:00
if ( aParent = = nil )
2000-01-03 11:00:14 +00:00
{
2004-05-19 01:36:37 +00:00
aParent = filesOwner ;
}
2005-04-10 22:21:59 +00:00
2004-05-19 01:36:37 +00:00
old = [ self connectorsForSource : anObject ofClass : [ NSNibConnector class ] ] ;
if ( [ old count ] > 0 )
{
[ [ old objectAtIndex : 0 ] setDestination : aParent ] ;
}
else
{
2005-06-17 04:41:24 +00:00
NSNibConnector * con = [ [ NSNibConnector alloc ] init ] ;
2004-05-19 01:36:37 +00:00
[ con setSource : anObject ] ;
[ con setDestination : aParent ] ;
[ self addConnector : ( id < IBConnectors > ) con ] ;
RELEASE ( con ) ;
}
2005-04-10 22:21:59 +00:00
2004-05-19 01:36:37 +00:00
/ *
* Make sure that there is a name for this object .
* /
if ( [ self nameForObject : anObject ] = = nil )
{
newObject = YES ;
[ self setName : nil forObject : anObject ] ;
}
/ *
* Add top - level objects to objectsView and open their editors .
* /
2004-06-29 03:27:37 +00:00
if ( [ anObject isKindOfClass : [ NSWindow class ] ] ||
[ anObject isKindOfClass : [ GSNibItem class ] ] )
2004-05-19 01:36:37 +00:00
{
[ objectsView addObject : anObject ] ;
2004-06-29 03:27:37 +00:00
[ topLevelObjects addObject : anObject ] ;
2004-05-19 01:36:37 +00:00
[ [ self openEditorForObject : anObject ] activate ] ;
if ( [ anObject isKindOfClass : [ NSWindow class ] ] = = YES )
{
[ anObject setReleasedWhenClosed : NO ] ;
}
}
2005-04-10 22:21:59 +00:00
else if ( ( aParent = = filesOwner || aParent = = nil ) &&
[ anObject isKindOfClass : [ NSMenu class ] ] = = NO )
{
if ( [ anObject isKindOfClass : [ NSObject class ] ] &&
[ anObject isKindOfClass : [ NSView class ] ] = = NO )
{
[ objectsView addObject : anObject ] ;
[ topLevelObjects addObject : anObject ] ;
}
else if ( [ anObject isKindOfClass : [ NSView class ] ] && [ anObject superview ] = = nil )
{
[ objectsView addObject : anObject ] ;
[ topLevelObjects addObject : anObject ] ;
}
}
2004-11-12 23:09:54 +00:00
/ *
* Check if it ' s a font manager .
* /
else if ( [ anObject isKindOfClass : [ NSFontManager class ] ] )
{
// if someone tries to attach a font manager , we must attach
// the proxy instead .
[ self _instantiateFontManager ] ;
}
2005-04-10 22:21:59 +00:00
2004-05-19 01:36:37 +00:00
/ *
* Add the current menu and any submenus .
* /
2004-11-12 23:09:54 +00:00
else if ( [ anObject isKindOfClass : [ NSMenu class ] ] = = YES )
2004-05-19 01:36:37 +00:00
{
2004-06-24 05:30:22 +00:00
BOOL isMainMenu = NO ;
2004-05-19 01:36:37 +00:00
// if there is no main menu and a menu gets added , it
// will become the main menu .
if ( [ self objectForName : @ "NSMenu" ] = = nil )
{
[ self setName : @ "NSMenu" forObject : anObject ] ;
[ objectsView addObject : anObject ] ;
2004-06-29 03:27:37 +00:00
[ topLevelObjects addObject : anObject ] ;
2004-06-24 05:30:22 +00:00
isMainMenu = YES ;
2004-05-19 01:36:37 +00:00
}
2004-05-29 19:18:22 +00:00
else
{
2004-06-24 05:30:22 +00:00
if ( [ [ anObject title ] isEqual : @ "Services" ] && [ self servicesMenu ] = = nil )
2004-05-29 19:18:22 +00:00
{
[ self setServicesMenu : anObject ] ;
}
2004-06-24 05:30:22 +00:00
else if ( [ [ anObject title ] isEqual : @ "Windows" ] && [ self windowsMenu ] = = nil )
2004-05-29 19:18:22 +00:00
{
[ self setWindowsMenu : anObject ] ;
}
}
2004-05-19 01:36:37 +00:00
[ [ self openEditorForObject : anObject ] activate ] ;
2004-06-24 05:30:22 +00:00
// if it ' s the main menu . . . locate it appropriately . . .
if ( isMainMenu )
{
NSRect frame = [ window frame ] ;
NSPoint origin = frame . origin ;
origin . y + = ( frame . size . height + 150 ) ;
// place the main menu appropriately . . .
[ [ anObject window ] setFrameTopLeftPoint : origin ] ;
}
2004-05-19 01:36:37 +00:00
}
/ *
* if this a scrollview , it is interesting to add its contentview
* if it is a tableview or a textview
* /
2004-11-12 23:09:54 +00:00
else if ( ( [ anObject isKindOfClass : [ NSScrollView class ] ] = = YES )
&& ( [ ( NSScrollView * ) anObject documentView ] ! = nil ) )
2004-05-19 01:36:37 +00:00
{
if ( [ [ anObject documentView ] isKindOfClass :
[ NSTableView class ] ] = = YES )
{
int i ;
int count ;
NSArray * tc ;
id tv = [ anObject documentView ] ;
tc = [ tv tableColumns ] ;
count = [ tc count ] ;
[ self attachObject : tv toParent : aParent ] ;
for ( i = 0 ; i < count ; i + + )
{
[ self attachObject : [ tc objectAtIndex : i ]
toParent : aParent ] ;
}
}
2004-11-30 04:51:19 +00:00
else if ( [ [ anObject documentView ] isKindOfClass : [ NSTextView class ] ] = = YES )
2004-05-19 01:36:37 +00:00
{
[ self attachObject : [ anObject documentView ] toParent : aParent ] ;
}
}
// Detect and add any connection the object might have .
// This is done so that any palette items which have predefined connections will be
// shown in the connections list .
if ( [ anObject respondsToSelector : @ selector ( action ) ] = = YES &&
[ anObject respondsToSelector : @ selector ( target ) ] = = YES &&
newObject = = YES )
{
SEL sel = [ anObject action ] ;
if ( sel ! = NULL )
{
NSString * label = NSStringFromSelector ( sel ) ;
id source = anObject ;
2005-06-17 04:41:24 +00:00
NSNibControlConnector * con = [ [ NSNibControlConnector alloc ] init ] ;
2005-02-13 14:22:04 +00:00
id destination = [ ( NSControl * ) anObject target ] ;
2004-05-19 01:36:37 +00:00
NSArray * sourceConnections = [ self connectorsForSource : source ] ;
// if it ' s a menu item we want to connect it to it ' s parent . . .
if ( [ anObject isKindOfClass : [ NSMenuItem class ] ] &&
[ label isEqual : @ "submenuAction:" ] )
{
destination = aParent ;
}
// if the connection needs to be made with the font manager , replace
// it with our proxy object and proceed with creating the connection .
2005-06-04 11:46:43 +00:00
if ( ( destination = = nil || destination = = [ NSFontManager sharedFontManager ] ) &&
2004-05-19 01:36:37 +00:00
[ classManager isAction : label ofClass : @ "NSFontManager" ] )
{
if ( ! fontManager )
{
// initialize font manager . . .
[ self _instantiateFontManager ] ;
}
// set the destination . . .
destination = fontManager ;
}
// if the destination is still nil , back off to the first responder .
if ( destination = = nil )
{
destination = firstResponder ;
}
// build the connection
[ con setSource : source ] ;
[ con setDestination : destination ] ;
[ con setLabel : label ] ;
// don ' t duplicate the connection if it already exists .
// if ( [ sourceConnections indexOfObjectIdenticalTo : con ] = = NSNotFound )
if ( [ sourceConnections containsObject : con ] = = NO )
{
// add it to our connections set .
[ self addConnector : ( id < IBConnectors > ) con ] ;
}
// destroy the connection in the object to
// prevent any conflict . The connections are restored when the
// . gorm is loaded , so there ' s no need for it anymore .
[ anObject setTarget : nil ] ;
[ anObject setAction : NULL ] ;
// release the connection .
RELEASE ( con ) ;
}
}
}
2005-04-11 20:42:33 +00:00
/ * *
* Attach all objects in anArray to the document with aParent .
* /
2004-05-19 01:36:37 +00:00
- ( void ) attachObjects : ( NSArray * ) anArray toParent : ( id ) aParent
{
NSEnumerator * enumerator = [ anArray objectEnumerator ] ;
NSObject * obj ;
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
{
[ self attachObject : obj toParent : aParent ] ;
}
}
2005-04-11 20:42:33 +00:00
/ * *
* Start the process of archiving .
* /
2004-05-19 01:36:37 +00:00
- ( void ) beginArchiving
{
NSEnumerator * enumerator ;
id < IBConnectors > con ;
id obj ;
/ *
* Map all connector sources and destinations to their name strings .
* Deactivate editors so they won ' t be archived .
* /
enumerator = [ connections objectEnumerator ] ;
while ( ( con = [ enumerator nextObject ] ) ! = nil )
{
if ( [ con isKindOfClass : [ GormObjectToEditor class ] ] = = YES )
{
[ savedEditors addObject : con ] ;
[ [ con destination ] deactivate ] ;
}
else if ( [ con isKindOfClass : [ GormEditorToParent class ] ] = = YES )
{
[ savedEditors addObject : con ] ;
}
else
{
NSString * name ;
obj = [ con source ] ;
name = [ self nameForObject : obj ] ;
2000-01-03 11:00:14 +00:00
[ con setSource : name ] ;
obj = [ con destination ] ;
name = [ self nameForObject : obj ] ;
[ con setDestination : name ] ;
}
}
[ connections removeObjectsInArray : savedEditors ] ;
2002-12-15 18:17:53 +00:00
NSDebugLog ( @ "*** customClassMap = %@" , [ classManager customClassMap ] ) ;
2002-12-22 00:33:44 +00:00
[ nameTable setObject : [ classManager customClassMap ] forKey : GSCustomClassMap ] ;
2002-10-13 06:04:05 +00:00
2000-01-03 11:00:14 +00:00
/ *
* Remove objects and connections that shouldn ' t be archived .
* /
2000-12-27 09:00:32 +00:00
NSMapRemove ( objToName , ( void * ) [ nameTable objectForKey : @ "NSOwner" ] ) ;
2000-01-03 11:00:14 +00:00
[ nameTable removeObjectForKey : @ "NSOwner" ] ;
2000-12-27 09:00:32 +00:00
NSMapRemove ( objToName , ( void * ) [ nameTable objectForKey : @ "NSFirst" ] ) ;
2000-01-03 11:00:14 +00:00
[ nameTable removeObjectForKey : @ "NSFirst" ] ;
2001-06-20 16:00:19 +00:00
/ * Add information about the NSOwner to the archive * /
NSMapInsert ( objToName , ( void * ) [ filesOwner className ] , ( void * ) @ "NSOwner" ) ;
2002-04-07 22:02:41 +00:00
[ nameTable setObject : [ filesOwner className ] forKey : @ "NSOwner" ] ;
2004-07-12 04:16:09 +00:00
/ *
* Set the appropriate profile so that we save the right versions of
* the classes for older GNUstep releases .
* /
[ filePrefsManager setClassVersions ] ;
2000-01-03 11:00:14 +00:00
}
2005-04-22 20:02:45 +00:00
- ( void ) changeToViewWithTag : ( int ) tag
2001-05-08 09:43:11 +00:00
{
switch ( tag )
{
2004-07-12 04:16:09 +00:00
case 0 : // objects
{
[ selectionBox setContentView : scrollView ] ;
2005-07-06 14:47:33 +00:00
[ self setSelectionFromEditor : objectsView ] ;
2004-07-12 04:16:09 +00:00
}
break ;
case 1 : // images
{
[ selectionBox setContentView : imagesScrollView ] ;
2005-07-06 14:47:33 +00:00
[ self setSelectionFromEditor : imagesView ] ;
2004-07-12 04:16:09 +00:00
}
break ;
case 2 : // sounds
{
[ selectionBox setContentView : soundsScrollView ] ;
2005-07-06 14:47:33 +00:00
[ self setSelectionFromEditor : soundsView ] ;
2004-07-12 04:16:09 +00:00
}
break ;
case 3 : // classes
{
NSArray * selection = [ [ ( id < IB > ) NSApp selectionOwner ] selection ] ;
2005-05-04 09:34:49 +00:00
[ selectionBox setContentView : classesView ] ;
2004-07-12 04:16:09 +00:00
// if something is selected , in the object view .
// show the equivalent class in the classes view .
if ( [ selection count ] > 0 )
{
id obj = [ selection objectAtIndex : 0 ] ;
2004-12-05 20:52:36 +00:00
[ classesView selectClassWithObject : obj ] ;
2004-07-12 04:16:09 +00:00
}
2005-07-06 14:47:33 +00:00
[ self setSelectionFromEditor : classesView ] ;
2004-07-12 04:16:09 +00:00
}
break ;
case 4 : // file prefs
{
[ selectionBox setContentView : filePrefsView ] ;
}
break ;
2001-05-08 09:43:11 +00:00
}
}
2005-04-22 20:02:45 +00:00
- ( void ) changeToTopLevelEditorAcceptingTypes : ( NSArray * ) types
2005-04-22 21:27:14 +00:00
andFileType : ( NSString * ) fileType
2005-04-22 20:02:45 +00:00
{
2005-04-24 00:15:57 +00:00
if ( [ objectsView acceptsTypeFromArray : types ] &&
fileType = = nil )
2005-04-22 20:02:45 +00:00
{
[ self changeToViewWithTag : 0 ] ;
}
2005-04-22 21:27:14 +00:00
else if ( [ imagesView acceptsTypeFromArray : types ] &&
[ [ imagesView fileTypes ] containsObject : fileType ] )
2005-04-22 20:02:45 +00:00
{
[ self changeToViewWithTag : 1 ] ;
}
2005-04-22 21:27:14 +00:00
else if ( [ soundsView acceptsTypeFromArray : types ] &&
[ [ soundsView fileTypes ] containsObject : fileType ] )
2005-04-22 20:02:45 +00:00
{
[ self changeToViewWithTag : 2 ] ;
}
2005-04-22 21:27:14 +00:00
else if ( [ classesView acceptsTypeFromArray : types ] &&
[ [ classesView fileTypes ] containsObject : fileType ] )
2005-04-22 20:02:45 +00:00
{
[ self changeToViewWithTag : 3 ] ;
}
}
/ * *
* Change the view in the document window .
* /
- ( void ) changeView : ( id ) sender
{
[ self changeToViewWithTag : [ sender tag ] ] ;
}
2005-04-11 20:42:33 +00:00
/ * *
* The class manager .
* /
2001-05-08 09:43:11 +00:00
- ( GormClassManager * ) classManager
{
return classManager ;
}
2005-04-11 20:42:33 +00:00
/ * *
* A Gorm document is encoded in the archive as a GSNibContainer .
* A class that the gnustep gui library knows about and can unarchive .
1999-12-13 17:01:35 +00:00
* /
- ( Class ) classForCoder
{
return [ GSNibContainer class ] ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns all connectors to destination .
* /
1999-12-08 15:04:57 +00:00
- ( NSArray * ) connectorsForDestination : ( id ) destination
{
return [ self connectorsForDestination : destination ofClass : 0 ] ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns all connectors to destination of class aConnectorClass .
* /
1999-12-08 15:04:57 +00:00
- ( NSArray * ) connectorsForDestination : ( id ) destination
ofClass : ( Class ) aConnectorClass
{
NSMutableArray * array = [ NSMutableArray arrayWithCapacity : 16 ] ;
NSEnumerator * enumerator = [ connections objectEnumerator ] ;
id < IBConnectors > c ;
while ( ( c = [ enumerator nextObject ] ) ! = nil )
{
if ( [ c destination ] = = destination
&& ( aConnectorClass = = 0 || aConnectorClass = = [ c class ] ) )
{
[ array addObject : c ] ;
}
}
return array ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns all connectors to source .
* /
1999-12-08 15:04:57 +00:00
- ( NSArray * ) connectorsForSource : ( id ) source
{
return [ self connectorsForSource : source ofClass : 0 ] ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns all connectors to a given source where the
* connectors are of aConnectorClass .
* /
1999-12-08 15:04:57 +00:00
- ( NSArray * ) connectorsForSource : ( id ) source
ofClass : ( Class ) aConnectorClass
{
NSMutableArray * array = [ NSMutableArray arrayWithCapacity : 16 ] ;
NSEnumerator * enumerator = [ connections objectEnumerator ] ;
id < IBConnectors > c ;
while ( ( c = [ enumerator nextObject ] ) ! = nil )
{
if ( [ c source ] = = source
&& ( aConnectorClass = = 0 || aConnectorClass = = [ c class ] ) )
{
[ array addObject : c ] ;
}
}
return array ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns YES , if the document contains anObject .
* /
1999-12-08 15:04:57 +00:00
- ( BOOL ) containsObject : ( id ) anObject
{
if ( [ self nameForObject : anObject ] = = nil )
{
return NO ;
}
return YES ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns YES , if the document contains an object with aName and
* parent .
* /
1999-12-08 15:04:57 +00:00
- ( BOOL ) containsObjectWithName : ( NSString * ) aName forParent : ( id ) parent
{
id obj = [ nameTable objectForKey : aName ] ;
if ( obj = = nil )
{
return NO ;
}
return YES ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Copy anObject to aPasteboard using aType . Returns YES , if
* successful .
* /
1999-12-08 15:04:57 +00:00
- ( BOOL ) copyObject : ( id ) anObject
type : ( NSString * ) aType
toPasteboard : ( NSPasteboard * ) aPasteboard
{
return [ self copyObjects : [ NSArray arrayWithObject : anObject ]
type : aType
toPasteboard : aPasteboard ] ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Copy all objects in anArray to aPasteboard using aType . Returns YES ,
* if successful .
* /
1999-12-08 15:04:57 +00:00
- ( BOOL ) copyObjects : ( NSArray * ) anArray
type : ( NSString * ) aType
toPasteboard : ( NSPasteboard * ) aPasteboard
{
2000-01-14 17:07:44 +00:00
NSEnumerator * enumerator ;
2004-05-13 05:13:36 +00:00
NSMutableSet * editorSet ;
2000-01-14 17:07:44 +00:00
id obj ;
2003-10-12 05:45:44 +00:00
NSMutableData * data ;
NSArchiver * archiver ;
2000-01-14 17:07:44 +00:00
/ *
* Remove all editors from the selected objects before archiving
* and restore them afterwards .
* /
2005-06-17 04:41:24 +00:00
editorSet = [ [ NSMutableSet alloc ] init ] ;
2000-01-14 17:07:44 +00:00
enumerator = [ anArray objectEnumerator ] ;
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
{
2004-03-24 03:08:02 +00:00
id editor = [ self editorForObject : obj create : NO ] ;
2000-01-14 17:07:44 +00:00
if ( editor ! = nil )
{
2004-05-13 05:13:36 +00:00
[ editorSet addObject : editor ] ;
2000-01-14 17:07:44 +00:00
[ editor deactivate ] ;
}
}
2003-10-12 05:45:44 +00:00
// encode the data
data = [ NSMutableData dataWithCapacity : 0 ] ;
archiver = [ [ NSArchiver alloc ] initForWritingWithMutableData : data ] ;
[ archiver encodeClassName : @ "GormCustomView"
intoClassName : @ "GSCustomView" ] ;
[ archiver encodeRootObject : anArray ] ;
// reactivate
2004-05-13 05:13:36 +00:00
enumerator = [ editorSet objectEnumerator ] ;
2000-01-14 17:07:44 +00:00
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
{
[ obj activate ] ;
}
2004-05-13 05:13:36 +00:00
RELEASE ( editorSet ) ;
1999-12-08 15:04:57 +00:00
[ aPasteboard declareTypes : [ NSArray arrayWithObject : aType ]
owner : self ] ;
2000-01-14 17:07:44 +00:00
return [ aPasteboard setData : data forType : aType ] ;
1999-12-08 15:04:57 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Create a subclass of the currently selected class in the classes view .
* /
2001-05-08 09:43:11 +00:00
- ( id ) createSubclass : ( id ) sender
{
2004-12-05 23:30:56 +00:00
[ classesView createSubclass ] ;
2001-06-20 16:00:19 +00:00
return self ;
2001-05-08 09:43:11 +00:00
}
2004-07-12 04:16:09 +00:00
// For debugging ONLY .
2004-05-13 05:13:36 +00:00
/ *
- ( id ) retain
{
NSLog ( @ "Document being retained... %d: %@" , [ self retainCount ] , self ) ;
return [ super retain ] ;
}
- ( oneway void ) release
{
NSLog ( @ "Document being released... %d: %@" , [ self retainCount ] , self ) ;
[ super release ] ;
}
2004-07-12 04:16:09 +00:00
* /
2004-05-13 05:13:36 +00:00
2005-04-11 20:42:33 +00:00
/ * *
* The given pasteboard chaned ownership .
* /
2004-07-12 04:16:09 +00:00
- ( void ) pasteboardChangedOwner : ( NSPasteboard * ) sender
2000-01-14 13:34:15 +00:00
{
2000-01-16 09:56:48 +00:00
NSDebugLog ( @ "Owner changed for %@" , sender ) ;
2000-01-14 13:34:15 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Dealloc all things owned by a GormDocument object .
* /
1999-12-08 15:04:57 +00:00
- ( void ) dealloc
{
1999-12-15 15:29:27 +00:00
[ [ NSNotificationCenter defaultCenter ] removeObserver : self ] ;
2005-03-08 05:11:41 +00:00
ASSIGN ( lastEditor , nil ) ;
2004-07-21 01:49:07 +00:00
// close the window . . .
2004-05-20 02:34:03 +00:00
[ window close ] ;
2004-07-21 01:49:07 +00:00
// Get rid of the selection box .
[ selectionBox removeFromSuperviewWithoutNeedingDisplay ] ;
// release the managers . . .
2001-05-08 09:43:11 +00:00
RELEASE ( classManager ) ;
2004-07-21 01:49:07 +00:00
RELEASE ( filePrefsManager ) ;
2004-07-21 02:58:36 +00:00
RELEASE ( filePrefsView ) ;
2004-07-21 01:49:07 +00:00
// release editors . . .
RELEASE ( savedEditors ) ;
RELEASE ( openEditors ) ;
// hidden objects . . .
2000-02-03 17:04:37 +00:00
RELEASE ( hidden ) ;
2004-07-21 01:49:07 +00:00
2003-03-03 09:15:48 +00:00
if ( objToName ! = 0 )
{
NSFreeMapTable ( objToName ) ;
}
2004-07-21 01:49:07 +00:00
2004-07-22 01:22:34 +00:00
// editor views . . .
1999-12-08 15:04:57 +00:00
RELEASE ( documentPath ) ;
2001-05-08 09:43:11 +00:00
RELEASE ( scrollView ) ;
2005-05-04 09:34:49 +00:00
RELEASE ( classesView ) ;
2004-07-21 01:49:07 +00:00
RELEASE ( soundsScrollView ) ;
RELEASE ( imagesScrollView ) ;
2004-07-22 01:22:34 +00:00
// windows . . .
2004-05-13 05:13:36 +00:00
RELEASE ( window ) ;
2004-07-21 02:03:59 +00:00
RELEASE ( filePrefsWindow ) ;
2005-04-10 22:21:59 +00:00
// resource managers
RELEASE ( resourceManagers ) ;
1999-12-08 15:04:57 +00:00
[ super dealloc ] ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Deteach anObject from the document .
* /
1999-12-08 15:04:57 +00:00
- ( void ) detachObject : ( id ) anObject
{
2004-05-08 15:42:27 +00:00
NSString * name = RETAIN ( [ self nameForObject : anObject ] ) ; // released at end of method . . .
2003-08-23 01:04:36 +00:00
GormClassManager * cm = [ self classManager ] ;
2000-01-03 11:00:14 +00:00
unsigned count ;
2003-08-23 05:49:26 +00:00
1999-12-14 17:38:17 +00:00
[ [ self editorForObject : anObject create : NO ] close ] ;
2000-01-03 11:00:14 +00:00
count = [ connections count ] ;
1999-12-08 15:04:57 +00:00
while ( count - - > 0 )
{
id < IBConnectors > con = [ connections objectAtIndex : count ] ;
if ( [ con destination ] = = anObject || [ con source ] = = anObject )
{
[ connections removeObjectAtIndex : count ] ;
}
}
2003-10-18 06:20:45 +00:00
2004-03-22 04:20:17 +00:00
// if the font manager is being reset , zero out the instance variable .
if ( [ name isEqual : @ "NSFont" ] )
{
fontManager = nil ;
}
1999-12-13 17:01:35 +00:00
if ( [ anObject isKindOfClass : [ NSWindow class ] ] = = YES
2005-01-31 06:32:16 +00:00
|| [ anObject isKindOfClass : [ NSMenu class ] ] = = YES
|| [ topLevelObjects containsObject : anObject ] = = YES )
1999-12-08 15:04:57 +00:00
{
1999-12-14 19:55:18 +00:00
[ objectsView removeObject : anObject ] ;
1999-12-08 15:04:57 +00:00
}
2004-05-29 19:18:22 +00:00
2004-06-29 03:27:37 +00:00
// if it ' s in the top level items array , remove it .
if ( [ topLevelObjects containsObject : anObject ] )
{
[ topLevelObjects removeObject : anObject ] ;
}
2004-05-29 19:18:22 +00:00
// eliminate it from being the windows / services menu , if it ' s being detached .
if ( [ anObject isKindOfClass : [ NSMenu class ] ] )
{
if ( [ self windowsMenu ] = = anObject )
{
[ self setWindowsMenu : nil ] ;
}
else if ( [ self servicesMenu ] = = anObject )
{
[ self setServicesMenu : nil ] ;
}
}
2000-01-03 11:00:14 +00:00
/ *
2005-01-22 17:16:16 +00:00
* Make sure this window isn ' t in the list of objects to be made visible
2000-01-03 11:00:14 +00:00
* on nib loading .
* /
2005-01-22 17:16:16 +00:00
if ( [ anObject isKindOfClass : [ NSWindow class ] ] )
{
[ self setObject : anObject isVisibleAtLaunch : NO ] ;
}
2000-01-03 11:00:14 +00:00
2003-10-18 06:20:45 +00:00
// some objects are given a name , some are not . The only ones we need
// to worry about are those that have names .
if ( name ! = nil )
2003-08-23 05:49:26 +00:00
{
2003-10-18 06:20:45 +00:00
// remove from custom class map . . .
NSDebugLog ( @ "Delete from custom class map -> %@" , name ) ;
2004-11-12 23:09:54 +00:00
[ cm removeCustomClassForName : name ] ;
2003-10-18 06:20:45 +00:00
if ( [ anObject isKindOfClass : [ NSScrollView class ] ] = = YES )
{
NSView * subview = [ anObject documentView ] ;
NSString * objName = [ self nameForObject : subview ] ;
NSDebugLog ( @ "Delete from custom class map -> %@" , objName ) ;
2004-11-12 23:09:54 +00:00
[ cm removeCustomClassForName : objName ] ;
2003-10-18 06:20:45 +00:00
}
// remove from name table . . .
[ nameTable removeObjectForKey : name ] ;
// free . . .
NSMapRemove ( objToName , ( void * ) anObject ) ;
RELEASE ( name ) ;
2003-08-23 05:49:26 +00:00
}
1999-12-08 15:04:57 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Detach every object in anArray from the document .
* /
1999-12-08 15:04:57 +00:00
- ( void ) detachObjects : ( NSArray * ) anArray
{
NSEnumerator * enumerator = [ anArray objectEnumerator ] ;
NSObject * obj ;
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
{
[ self detachObject : obj ] ;
}
}
2005-04-11 20:42:33 +00:00
/ * *
* The path to where the . gorm file is saved .
* /
1999-12-08 15:04:57 +00:00
- ( NSString * ) documentPath
{
return documentPath ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Add an outlet / action to the classes view .
* /
2004-05-19 01:36:37 +00:00
- ( id ) addAttributeToClass : ( id ) sender
2001-12-19 07:13:54 +00:00
{
2004-05-19 01:36:37 +00:00
[ classesView addAttributeToClass ] ;
return self ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Remove a class from the classes view
* /
2004-05-19 01:36:37 +00:00
- ( id ) remove : ( id ) sender
{
2004-12-05 23:30:56 +00:00
[ classesView deleteSelection ] ;
2002-07-12 05:46:29 +00:00
return self ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Parse a header into the classes view .
* /
2001-12-19 07:13:54 +00:00
- ( id ) loadClass : ( id ) sender
{
NSArray * fileTypes = [ NSArray arrayWithObjects : @ "h" , @ "H" , nil ] ;
NSOpenPanel * oPanel = [ NSOpenPanel openPanel ] ;
int result ;
[ oPanel setAllowsMultipleSelection : NO ] ;
[ oPanel setCanChooseFiles : YES ] ;
[ oPanel setCanChooseDirectories : NO ] ;
result = [ oPanel runModalForDirectory : nil
file : nil
types : fileTypes ] ;
if ( result = = NSOKButton )
{
2004-11-27 10:56:40 +00:00
NSString * fileName = [ oPanel filename ] ;
2004-11-27 22:38:53 +00:00
NS_DURING
2004-11-27 10:56:40 +00:00
{
2004-11-27 22:38:53 +00:00
if ( ! [ classManager parseHeader : fileName ] )
{
2004-11-30 04:51:19 +00:00
NSString * file = [ fileName lastPathComponent ] ;
2004-11-27 22:38:53 +00:00
NSString * message = [ NSString stringWithFormat :
2004-11-30 04:51:19 +00:00
_ ( @ "Unable to parse class in %@" ) , file ] ;
2004-11-27 22:38:53 +00:00
NSRunAlertPanel ( _ ( @ "Problem parsing class" ) ,
message ,
nil , nil , nil ) ;
}
else
{
return self ;
}
}
NS_HANDLER
{
NSString * message = [ localException reason ] ;
2004-11-27 10:56:40 +00:00
NSRunAlertPanel ( _ ( @ "Problem parsing class" ) ,
message ,
nil , nil , nil ) ;
}
2004-11-27 22:38:53 +00:00
NS_ENDHANDLER
2001-12-19 07:13:54 +00:00
}
return nil ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Create the class files for the selected class .
* /
2001-07-06 17:10:51 +00:00
- ( id ) createClassFiles : ( id ) sender
{
NSSavePanel * sp ;
2004-12-05 23:30:56 +00:00
NSString * className = [ classesView selectedClassName ] ;
2001-07-06 17:10:51 +00:00
int result ;
2002-11-23 22:52:27 +00:00
2001-07-06 17:10:51 +00:00
sp = [ NSSavePanel savePanel ] ;
[ sp setRequiredFileType : @ "m" ] ;
2003-05-24 12:40:54 +00:00
[ sp setTitle : _ ( @ "Save source file as..." ) ] ;
2001-07-06 17:10:51 +00:00
if ( documentPath = = nil )
2002-12-22 00:33:44 +00:00
{
result = [ sp runModalForDirectory : NSHomeDirectory ( )
file : [ className stringByAppendingPathExtension : @ "m" ] ] ;
}
2001-07-06 17:10:51 +00:00
else
2002-12-22 00:33:44 +00:00
{
result = [ sp runModalForDirectory :
[ documentPath stringByDeletingLastPathComponent ]
file : [ className stringByAppendingPathExtension : @ "m" ] ] ;
}
2001-07-06 17:10:51 +00:00
if ( result = = NSOKButton )
{
NSString * sourceName = [ sp filename ] ;
NSString * headerName ;
[ sp setRequiredFileType : @ "h" ] ;
2003-05-24 12:40:54 +00:00
[ sp setTitle : _ ( @ "Save header file as..." ) ] ;
2001-07-06 17:10:51 +00:00
result = [ sp runModalForDirectory :
[ sourceName stringByDeletingLastPathComponent ]
file :
[ [ [ sourceName lastPathComponent ]
stringByDeletingPathExtension ]
stringByAppendingString : @ ".h" ] ] ;
if ( result = = NSOKButton )
{
headerName = [ sp filename ] ;
2003-02-13 13:32:59 +00:00
NSDebugLog ( @ "Saving %@" , className ) ;
2002-11-23 22:52:27 +00:00
if ( ! [ classManager makeSourceAndHeaderFilesForClass : className
withName : sourceName
and : headerName ] )
2001-07-06 17:10:51 +00:00
{
2003-05-24 12:40:54 +00:00
NSRunAlertPanel ( _ ( @ "Alert" ) ,
_ ( @ "Could not create the class's file" ) ,
2002-11-23 22:52:27 +00:00
nil , nil , nil ) ;
2001-07-06 17:10:51 +00:00
}
2002-11-23 22:52:27 +00:00
return self ;
2001-07-06 17:10:51 +00:00
}
}
return nil ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Close anEditor for anObject .
* /
2003-05-10 21:19:25 +00:00
- ( void ) editor : ( id < IBEditors , IBSelectionOwners > ) anEditor didCloseForObject : ( id ) anObject
2000-01-04 16:25:39 +00:00
{
NSArray * links ;
/ *
* If there is a link from this editor to a parent , remove it .
* /
links = [ self connectorsForSource : anEditor
ofClass : [ GormEditorToParent class ] ] ;
NSAssert ( [ links count ] < 2 , NSInternalInconsistencyException ) ;
if ( [ links count ] = = 1 )
{
[ connections removeObjectIdenticalTo : [ links objectAtIndex : 0 ] ] ;
}
/ *
* Remove the connection linking the object to this editor
* /
links = [ self connectorsForSource : anObject
ofClass : [ GormObjectToEditor class ] ] ;
NSAssert ( [ links count ] < 2 , NSInternalInconsistencyException ) ;
2002-08-14 00:01:42 +00:00
if ( [ links count ] = = 1 )
{
[ connections removeObjectIdenticalTo : [ links objectAtIndex : 0 ] ] ;
}
2000-01-04 16:25:39 +00:00
2004-05-13 05:13:36 +00:00
/ *
* Add to the master list of editors for this document
* /
2004-05-13 22:48:14 +00:00
[ openEditors removeObjectIdenticalTo : anEditor ] ;
2004-05-13 05:13:36 +00:00
2000-01-04 16:25:39 +00:00
/ *
* Make sure that this editor is not the selection owner .
* /
2003-05-25 19:08:36 +00:00
if ( [ ( id < IB > ) NSApp selectionOwner ] = =
2003-05-10 21:19:25 +00:00
anEditor )
2000-01-04 16:25:39 +00:00
{
[ self resignSelectionForEditor : anEditor ] ;
}
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns an editor for anObject , if flag is YES , it creates a new
* editor , if one doesn ' t currently exist .
* /
2000-01-04 16:25:39 +00:00
- ( id < IBEditors > ) editorForObject : ( id ) anObject
create : ( BOOL ) flag
{
return [ self editorForObject : anObject inEditor : nil create : flag ] ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns the editor for anObject , in the editor anEditor . If flag is
* YES , an editor is created if one doesn ' t already exist .
* /
2000-01-04 16:25:39 +00:00
- ( id < IBEditors > ) editorForObject : ( id ) anObject
inEditor : ( id < IBEditors > ) anEditor
create : ( BOOL ) flag
{
NSArray * links ;
/ *
* Look up the editor links for the object to see if it already has an
* editor . If it does return it , otherwise create a new editor and a
* link to it if the flag is set .
* /
links = [ self connectorsForSource : anObject
ofClass : [ GormObjectToEditor class ] ] ;
if ( [ links count ] = = 0 && flag = = YES )
{
2004-07-27 06:20:45 +00:00
Class eClass = NSClassFromString ( [ anObject editorClassName ] ) ;
2000-01-04 16:25:39 +00:00
id < IBEditors > editor ;
id < IBConnectors > link ;
editor = [ [ eClass alloc ] initWithObject : anObject inDocument : self ] ;
2005-06-17 04:41:24 +00:00
link = AUTORELEASE ( [ [ GormObjectToEditor alloc ] init ] ) ;
2000-01-04 16:25:39 +00:00
[ link setSource : anObject ] ;
[ link setDestination : editor ] ;
[ connections addObject : link ] ;
2004-05-13 22:48:14 +00:00
2004-07-28 03:54:42 +00:00
if ( ! [ openEditors containsObject : editor ] && editor ! = nil )
2004-05-13 05:13:36 +00:00
{
2004-05-13 22:48:14 +00:00
[ openEditors addObject : editor ] ;
2004-05-13 05:13:36 +00:00
}
2000-01-14 13:34:15 +00:00
if ( anEditor = = nil )
{
/ *
* By default all editors are owned by the top - level editor of
* the document .
* /
anEditor = objectsView ;
}
if ( anEditor ! = editor )
2000-01-04 16:25:39 +00:00
{
/ *
2000-01-14 13:34:15 +00:00
* Link to the parent of the editor .
2000-01-04 16:25:39 +00:00
* /
2005-06-17 04:41:24 +00:00
link = AUTORELEASE ( [ [ GormEditorToParent alloc ] init ] ) ;
2000-01-04 16:25:39 +00:00
[ link setSource : editor ] ;
[ link setDestination : anEditor ] ;
[ connections addObject : link ] ;
}
2002-08-14 00:01:42 +00:00
else
{
2002-12-27 23:57:35 +00:00
NSDebugLog ( @ "WARNING anEditor = editor" ) ;
2002-08-14 00:01:42 +00:00
}
2005-04-11 05:09:40 +00:00
2002-08-14 00:01:42 +00:00
[ editor activate ] ;
2003-05-10 21:19:25 +00:00
RELEASE ( ( NSObject * ) editor ) ;
2005-04-11 04:05:30 +00:00
2000-01-04 16:25:39 +00:00
return editor ;
}
2002-08-14 00:01:42 +00:00
else if ( [ links count ] = = 0 )
{
return nil ;
}
2000-01-04 16:25:39 +00:00
else
{
2002-08-14 00:01:42 +00:00
[ [ [ links lastObject ] destination ] activate ] ;
2000-01-04 16:25:39 +00:00
return [ [ links lastObject ] destination ] ;
}
}
2005-04-11 20:42:33 +00:00
/ * *
* Stop the archiving process .
* /
2000-01-03 11:00:14 +00:00
- ( void ) endArchiving
{
NSEnumerator * enumerator ;
id < IBConnectors > con ;
id obj ;
2004-07-12 04:16:09 +00:00
/ *
* Restore class versions .
* /
[ filePrefsManager restoreClassVersions ] ;
2000-01-03 11:00:14 +00:00
/ *
* Restore removed objects .
* /
[ nameTable setObject : filesOwner forKey : @ "NSOwner" ] ;
2000-12-27 09:00:32 +00:00
NSMapInsert ( objToName , ( void * ) filesOwner , ( void * ) @ "NSOwner" ) ;
2002-10-26 03:39:55 +00:00
2004-05-19 01:36:37 +00:00
[ nameTable setObject : firstResponder forKey : @ "NSFirst" ] ;
NSMapInsert ( objToName , ( void * ) firstResponder , ( void * ) @ "NSFirst" ) ;
2001-05-08 09:43:11 +00:00
2004-05-19 01:36:37 +00:00
/ *
* Map all connector source and destination names to their objects .
* /
enumerator = [ connections objectEnumerator ] ;
while ( ( con = [ enumerator nextObject ] ) ! = nil )
{
NSString * name ;
name = ( NSString * ) [ con source ] ;
obj = [ self objectForName : name ] ;
[ con setSource : obj ] ;
name = ( NSString * ) [ con destination ] ;
obj = [ self objectForName : name ] ;
[ con setDestination : obj ] ;
}
2001-05-08 09:43:11 +00:00
2004-05-19 01:36:37 +00:00
/ *
* Restore editor links and reactivate the editors .
* /
[ connections addObjectsFromArray : savedEditors ] ;
enumerator = [ savedEditors objectEnumerator ] ;
while ( ( con = [ enumerator nextObject ] ) ! = nil )
{
if ( [ [ con source ] isKindOfClass : [ NSView class ] ] = = NO )
[ [ con destination ] activate ] ;
}
[ savedEditors removeAllObjects ] ;
}
2001-05-08 09:43:11 +00:00
2005-04-11 20:42:33 +00:00
/ * *
* Forces the closing of all editors in the document .
* /
2004-05-19 01:36:37 +00:00
- ( void ) closeAllEditors
{
NSEnumerator * enumerator ;
id < IBConnectors > con ;
NSMutableArray * editors = [ NSMutableArray array ] ;
2002-03-26 17:15:26 +00:00
2004-05-19 01:36:37 +00:00
// remove the editor connections from the connection array . . .
enumerator = [ connections objectEnumerator ] ;
while ( ( con = [ enumerator nextObject ] ) ! = nil )
{
if ( [ con isKindOfClass : [ GormObjectToEditor class ] ] = = YES )
{
[ editors addObject : con ] ;
}
else if ( [ con isKindOfClass : [ GormEditorToParent class ] ] = = YES )
{
[ editors addObject : con ] ;
}
}
[ connections removeObjectsInArray : editors ] ;
[ editors removeAllObjects ] ;
2001-05-08 09:43:11 +00:00
2004-05-19 01:36:37 +00:00
// Close all of the editors & get all of the objects out .
// copy the array , since the close method calls editor : didCloseForObject :
// and would effect the array during the execution of
// makeObjectsPerformSelector : .
[ editors addObjectsFromArray : openEditors ] ;
[ editors makeObjectsPerformSelector : @ selector ( close ) ] ;
[ openEditors removeAllObjects ] ;
2004-07-21 01:49:07 +00:00
// [ editors makeObjectsPerformSelector : @ selector ( release ) ] ;
2004-05-19 01:36:37 +00:00
[ editors removeAllObjects ] ;
2001-05-08 09:43:11 +00:00
2004-05-19 01:36:37 +00:00
// Close the editors in the document window . . .
2004-08-11 11:16:35 +00:00
// don ' t worry about the "classesView" since it ' s not really an
2004-05-19 01:36:37 +00:00
// editor .
[ objectsView close ] ;
[ imagesView close ] ;
[ soundsView close ] ;
}
1999-12-15 15:29:27 +00:00
2005-04-11 20:42:33 +00:00
/ * *
* Handle all notifications . Checks the value of [ aNotification name ]
* against the set of notifications this class responds to and takes
* appropriate action .
* /
2004-05-19 01:36:37 +00:00
- ( void ) handleNotification : ( NSNotification * ) aNotification
{
NSString * name = [ aNotification name ] ;
NSNotificationCenter * nc = [ NSNotificationCenter defaultCenter ] ;
if ( [ name isEqual : NSWindowWillCloseNotification ] = = YES )
{
NSEnumerator * enumerator ;
id obj ;
2003-01-02 06:17:15 +00:00
2004-05-19 01:36:37 +00:00
enumerator = [ nameTable objectEnumerator ] ;
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
2003-01-02 06:17:15 +00:00
{
2004-07-21 01:49:07 +00:00
/ *
2004-05-19 01:36:37 +00:00
if ( [ obj isKindOfClass : [ NSMenu class ] ] = = YES )
{
if ( [ [ obj window ] isVisible ] = = YES )
{
[ obj close ] ;
}
}
2004-07-21 01:49:07 +00:00
else
* /
if ( [ obj isKindOfClass : [ NSWindow class ] ] = = YES )
2004-05-19 01:36:37 +00:00
{
2004-09-08 01:04:03 +00:00
// [ obj setReleasedWhenClosed : YES ] ;
2004-07-21 01:49:07 +00:00
[ obj close ] ;
2004-09-08 01:04:03 +00:00
RELEASE ( obj ) ;
2004-05-19 01:36:37 +00:00
}
}
2004-07-21 01:49:07 +00:00
2004-05-19 01:36:37 +00:00
// deactivate the document . . .
[ self setDocumentActive : NO ] ;
[ self closeAllEditors ] ; // shut down all of the editors . .
2004-07-21 01:49:07 +00:00
[ nc postNotificationName : IBWillCloseDocumentNotification object : self ] ;
2004-05-19 01:36:37 +00:00
[ nc removeObserver : self ] ; // stop listening to all notifications .
}
else if ( [ name isEqual : NSWindowDidBecomeKeyNotification ] = = YES )
{
[ self setDocumentActive : YES ] ;
}
else if ( [ name isEqual : NSWindowWillMiniaturizeNotification ] = = YES )
{
[ self setDocumentActive : NO ] ;
}
else if ( [ name isEqual : NSWindowDidDeminiaturizeNotification ] = = YES )
{
[ self setDocumentActive : YES ] ;
}
else if ( [ name isEqual : IBWillBeginTestingInterfaceNotification ] = = YES )
{
if ( [ window isVisible ] = = YES )
{
[ hidden addObject : window ] ;
[ window setExcludedFromWindowsMenu : YES ] ;
[ window orderOut : self ] ;
}
if ( [ ( id < IB > ) NSApp activeDocument ] = = self )
{
NSEnumerator * enumerator ;
id obj ;
2003-01-02 06:17:15 +00:00
2004-05-19 01:36:37 +00:00
enumerator = [ nameTable objectEnumerator ] ;
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
2003-01-02 06:17:15 +00:00
{
2004-05-19 01:36:37 +00:00
if ( [ obj isKindOfClass : [ NSMenu class ] ] = = YES )
{
if ( [ [ obj window ] isVisible ] = = YES )
{
[ hidden addObject : obj ] ;
[ obj close ] ;
}
}
else if ( [ obj isKindOfClass : [ NSWindow class ] ] = = YES )
{
if ( [ obj isVisible ] = = YES )
{
[ hidden addObject : obj ] ;
[ obj orderOut : self ] ;
}
}
2003-01-02 06:17:15 +00:00
}
}
1999-12-08 15:04:57 +00:00
}
2004-05-19 01:36:37 +00:00
else if ( [ name isEqual : IBWillEndTestingInterfaceNotification ] = = YES )
{
if ( [ hidden count ] > 0 )
{
NSEnumerator * enumerator ;
id obj ;
enumerator = [ hidden objectEnumerator ] ;
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
{
if ( [ obj isKindOfClass : [ NSMenu class ] ] = = YES )
{
[ obj display ] ;
}
else if ( [ obj isKindOfClass : [ NSWindow class ] ] = = YES )
{
[ obj orderFront : self ] ;
}
}
[ hidden removeAllObjects ] ;
[ window setExcludedFromWindowsMenu : NO ] ;
}
}
else if ( [ name isEqual : IBClassNameChangedNotification ] = = YES )
{
[ classesView reloadData ] ;
2004-12-11 05:24:12 +00:00
[ self setSelectionFromEditor : nil ] ;
2004-06-30 05:22:25 +00:00
[ self touch ] ;
2004-05-19 01:36:37 +00:00
}
else if ( [ name isEqual : IBInspectorDidModifyObjectNotification ] = = YES )
{
[ classesView reloadData ] ;
2004-06-30 05:22:25 +00:00
[ self touch ] ;
2004-05-19 01:36:37 +00:00
}
else if ( [ name isEqual : GormDidModifyClassNotification ] = = YES )
{
if ( [ classesView isEditing ] = = NO )
{
[ classesView reloadData ] ;
}
}
else if ( [ name isEqual : GormDidAddClassNotification ] )
{
2004-12-03 12:19:18 +00:00
NSArray * customClasses = [ classManager allCustomClassNames ] ;
NSString * newClass = [ customClasses lastObject ] ;
2004-05-19 01:36:37 +00:00
// go to the class which was just loaded in the classes view . . .
[ classesView reloadData ] ;
2005-05-04 09:34:49 +00:00
[ selectionBox setContentView : classesView ] ;
2004-12-03 12:19:18 +00:00
if ( newClass ! = nil )
{
2004-12-05 20:52:36 +00:00
[ classesView selectClass : newClass ] ;
2004-12-03 12:19:18 +00:00
}
2004-05-19 01:36:37 +00:00
}
2005-04-10 22:21:59 +00:00
else if ( [ name isEqual : IBResourceManagerRegistryDidChangeNotification ] )
{
if ( resourceManagers ! = nil )
{
Class cls = [ aNotification object ] ;
id mgr = [ ( IBResourceManager * ) [ cls alloc ] initWithDocument : self ] ;
[ resourceManagers addObject : mgr ] ;
}
}
1999-12-08 15:04:57 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Create an instance of a given class .
* /
2001-05-08 09:43:11 +00:00
- ( id ) instantiateClass : ( id ) sender
{
2004-12-05 23:30:56 +00:00
NSString * object = [ classesView selectedClassName ] ;
GSNibItem * item = nil ;
2004-05-20 02:34:03 +00:00
2004-12-05 23:30:56 +00:00
if ( [ object isEqualToString : @ "FirstResponder" ] )
return nil ;
if ( [ classManager isSuperclass : @ "NSView" linkedToClass : object ] ||
[ object isEqual : @ "NSView" ] )
2001-05-08 09:43:11 +00:00
{
2004-12-05 23:30:56 +00:00
Class cls ;
NSString * className = object ;
BOOL isCustom = [ classManager isCustomClass : object ] ;
id instance ;
2004-05-20 02:34:03 +00:00
2004-12-05 23:30:56 +00:00
if ( isCustom )
2001-05-08 09:43:11 +00:00
{
2004-12-05 23:30:56 +00:00
className = [ classManager nonCustomSuperClassOf : object ] ;
}
// instantiate the object or it ' s substitute . . .
cls = NSClassFromString ( className ) ;
if ( [ cls respondsToSelector : @ selector ( allocSubstitute ) ] )
{
instance = [ cls allocSubstitute ] ;
}
else
{
instance = [ cls alloc ] ;
}
// give it some initial dimensions . . .
if ( [ instance respondsToSelector : @ selector ( initWithFrame : ) ] )
{
instance = [ instance initWithFrame : NSMakeRect ( 10 , 10 , 380 , 280 ) ] ;
}
else
{
instance = [ instance init ] ;
2001-05-08 09:43:11 +00:00
}
2004-12-05 23:30:56 +00:00
// add it to the top level objects . . .
[ self setName : nil forObject : instance ] ;
[ self attachObject : instance toParent : nil ] ;
// we want to record if it ' s custom or not and act appropriately . . .
if ( isCustom )
{
NSString * name = [ self nameForObject : instance ] ;
[ classManager setCustomClass : object
forName : name ] ;
}
[ selectionBox setContentView : scrollView ] ;
NSLog ( @ "Instantiate NSView subclass %@" , object ) ;
2001-05-08 09:43:11 +00:00
}
2004-12-05 23:30:56 +00:00
else
{
item = [ [ GormObjectProxy alloc ] initWithClassName : object
frame : NSMakeRect ( 0 , 0 , 0 , 0 ) ] ;
[ self setName : nil forObject : item ] ;
[ self attachObject : item toParent : nil ] ;
[ selectionBox setContentView : scrollView ] ;
}
2003-05-25 19:08:36 +00:00
return self ;
2001-05-08 09:43:11 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns YES , if document is active .
* /
2000-01-04 16:25:39 +00:00
- ( BOOL ) isActive
{
return isActive ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns the name for anObject .
* /
1999-12-08 15:04:57 +00:00
- ( NSString * ) nameForObject : ( id ) anObject
{
1999-12-13 17:01:35 +00:00
return ( NSString * ) NSMapGet ( objToName , ( void * ) anObject ) ;
1999-12-08 15:04:57 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns the object for name .
* /
1999-12-08 15:04:57 +00:00
- ( id ) objectForName : ( NSString * ) name
{
1999-12-13 17:01:35 +00:00
return [ nameTable objectForKey : name ] ;
1999-12-08 15:04:57 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns all objects in the document .
* /
1999-12-08 15:04:57 +00:00
- ( NSArray * ) objects
{
return [ nameTable allValues ] ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Returns YES , if the current select on the classes view is a class .
* /
2004-05-19 01:36:37 +00:00
- ( BOOL ) classIsSelected
{
2004-12-05 20:52:36 +00:00
return [ classesView currentSelectionIsClass ] ;
}
2004-05-19 01:36:37 +00:00
2005-04-11 20:42:33 +00:00
/ * *
* Remove all instances of a given class .
* /
2004-12-16 10:38:14 +00:00
- ( void ) removeAllInstancesOfClass : ( NSString * ) className
{
2004-12-17 10:49:01 +00:00
[ objectsView removeAllInstancesOfClass : className ] ;
2004-12-16 10:38:14 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Select a class in the classes view
* /
2004-12-05 20:52:36 +00:00
- ( void ) selectClass : ( NSString * ) className
{
[ classesView selectClass : className ] ;
2004-05-19 01:36:37 +00:00
}
2005-06-10 11:43:51 +00:00
/ * *
* Select a class in the classes view
* /
- ( void ) selectClass : ( NSString * ) className editClass : ( BOOL ) flag
{
[ classesView selectClass : className editClass : flag ] ;
}
2005-04-11 20:42:33 +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
2005-07-05 14:58:42 +00:00
* may be added to as time goes on to make sure that it ' s possible
2005-04-11 20:42:33 +00:00
* to repair old . gorm files .
* /
2004-03-13 12:40:44 +00:00
- ( void ) _repairFile
{
2004-04-05 02:19:52 +00:00
NSEnumerator * en = [ [ nameTable allKeys ] objectEnumerator ] ;
2004-03-13 12:40:44 +00:00
NSString * key = nil ;
2005-04-17 16:14:12 +00:00
2004-12-18 15:06:18 +00:00
NSRunAlertPanel ( _ ( @ "Warning" ) ,
_ ( @ "You are running with 'GormRepairFileOnLoad' set to YES." ) ,
nil , nil , nil ) ;
2004-03-13 12:40:44 +00:00
while ( ( key = [ en nextObject ] ) ! = nil )
{
id obj = [ 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 , [ self nameForObject : obj ] ) ;
2004-04-30 22:34:43 +00:00
[ self detachObjects : menus ] ;
[ self 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 .
2004-05-08 15:42:27 +00:00
RETAIN ( obj ) ; // extra retain to stave off autorelease . . .
2004-03-13 12:40:44 +00:00
}
}
if ( [ obj isKindOfClass : [ NSMenuItem class ] ] )
{
id m = [ obj menu ] ;
if ( m = = nil )
{
2004-04-30 22:34:43 +00:00
id sm = [ obj submenu ] ;
2004-03-13 12:40:44 +00:00
NSLog ( @ "Found and removed a dangling menu item %@, %@." , obj , [ self nameForObject : obj ] ) ;
2004-04-30 22:34:43 +00:00
[ self detachObject : obj ] ;
2004-03-13 12:40:44 +00:00
2004-04-30 22:34:43 +00:00
// if there are any submenus , detach those as well .
if ( sm ! = nil )
{
NSArray * menus = findAll ( sm ) ;
[ self detachObjects : menus ] ;
}
2004-03-13 12:40:44 +00:00
}
}
2004-11-18 05:34:19 +00:00
/ * *
* 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 &&
[ topLevelObjects containsObject : obj ] = = NO &&
[ obj hasSuperviewKindOfClass : [ NSTabView class ] ] = = NO )
{
NSLog ( @ "Found and removed an orphan view %@, %@" , obj , [ self nameForObject : obj ] ) ;
[ self detachObject : obj ] ;
}
}
2004-03-13 12:40:44 +00:00
}
}
2005-07-05 14:58:42 +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 = [ nameTable objectEnumerator ] ;
id obj = nil ;
while ( ( obj = [ en nextObject ] ) ! = nil )
{
if ( [ obj isKindOfClass : cls ] )
{
return YES ;
}
}
return NO ;
}
2005-04-11 20:42:33 +00:00
/ * *
* This assumes we have an empty document to start with - the loaded
2000-01-04 17:46:26 +00:00
* document is merged in to it .
* /
- ( id ) loadDocument : ( NSString * ) aFile
{
2004-06-03 04:40:48 +00:00
NS_DURING
2002-10-31 15:00:17 +00:00
{
2004-06-03 04:40:48 +00:00
NSNotificationCenter * nc = [ NSNotificationCenter defaultCenter ] ;
NSMutableDictionary * nt ;
NSMutableDictionary * cc ;
2004-06-24 05:30:22 +00:00
NSData * data ;
2004-06-03 04:40:48 +00:00
NSUnarchiver * u ;
2004-06-24 05:30:22 +00:00
GSNibContainer * c ;
2004-06-03 04:40:48 +00:00
NSEnumerator * enumerator ;
2004-06-24 05:30:22 +00:00
id < IBConnectors > con ;
NSString * ownerClass , * key ;
2004-06-03 04:40:48 +00:00
NSFileManager * mgr = [ NSFileManager defaultManager ] ;
2004-06-24 05:30:22 +00:00
BOOL isDir = NO ;
NSDirectoryEnumerator * dirEnumerator ;
BOOL repairFile = [ [ NSUserDefaults standardUserDefaults ] boolForKey : @ "GormRepairFileOnLoad" ] ;
NSMenu * mainMenu ;
2005-02-13 09:40:12 +00:00
NSString * ext = [ aFile pathExtension ] ;
2005-04-17 16:14:12 +00:00
GormPalettesManager * palettesManager = [ ( id < Gorm > ) NSApp palettesManager ] ;
NSDictionary * substituteClasses = [ palettesManager substituteClasses ] ;
NSEnumerator * en = [ substituteClasses keyEnumerator ] ;
NSString * subClassName = nil ;
2005-07-07 17:23:56 +00:00
unsigned int version = NSNotFound ;
2004-06-24 05:30:22 +00:00
2005-02-13 09:40:12 +00:00
// If someone attempts to open a . gmodel using open or in a
// workspace manager , open it . . otherwise open the . gorm file .
if ( [ ext isEqual : @ "gmodel" ] )
{
return [ self openGModel : aFile ] ;
}
2004-06-03 04:40:48 +00:00
if ( [ mgr fileExistsAtPath : aFile isDirectory : & isDir ] )
2002-10-31 15:00:17 +00:00
{
2004-06-03 04:40:48 +00:00
// if the data is in a directory , then load from objects . gorm
if ( isDir = = NO )
{
NSString * lastComponent = [ aFile lastPathComponent ] ;
NSString * parent = [ aFile stringByDeletingLastPathComponent ] ;
NSString * parentExt = [ parent pathExtension ] ;
// test if we ' re doing it wrong . . .
if ( [ lastComponent isEqual : @ "objects.gorm" ] &&
[ parentExt isEqual : @ "gorm" ] )
{
2005-02-05 14:11:57 +00:00
NSRunAlertPanel ( _ ( @ "Problem Loading" ) ,
2004-06-03 04:40:48 +00:00
_ ( @ "Cannot load directly from objects.gorm file, please load from the gorm package." ) ,
2005-02-05 14:11:57 +00:00
_ ( @ "OK" ) , nil , nil ) ;
2004-06-03 04:40:48 +00:00
return nil ;
}
data = [ NSData dataWithContentsOfFile : aFile ] ;
NSDebugLog ( @ "Loaded data from file..." ) ;
}
else
2004-05-08 20:04:13 +00:00
{
2004-06-03 04:40:48 +00:00
NSString * newFileName ;
newFileName = [ aFile stringByAppendingPathComponent : @ "objects.gorm" ] ;
data = [ NSData dataWithContentsOfFile : newFileName ] ;
NSDebugLog ( @ "Loaded data from %@..." , newFileName ) ;
2004-05-08 20:04:13 +00:00
}
2002-10-31 15:00:17 +00:00
}
else
{
2004-06-03 04:40:48 +00:00
// no file exists . . .
data = nil ;
2002-10-31 15:00:17 +00:00
}
2004-06-03 04:40:48 +00:00
// check the data . . .
if ( data = = nil )
2002-10-31 15:00:17 +00:00
{
2005-02-05 14:11:57 +00:00
NSRunAlertPanel ( _ ( @ "Problem Loading" ) ,
2004-06-03 04:40:48 +00:00
[ NSString stringWithFormat : @ "Could not read '%@' data" , aFile ] ,
2005-02-05 14:11:57 +00:00
_ ( @ "OK" ) , nil , nil ) ;
2004-06-03 04:40:48 +00:00
return nil ;
2002-10-31 15:00:17 +00:00
}
2004-06-03 04:40:48 +00:00
/ *
* Create an unarchiver , and use it to unarchive the nib 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 ] ;
2005-06-04 11:46:43 +00:00
// special internal classes
2004-06-03 04:40:48 +00:00
[ u decodeClassName : @ "GSNibContainer"
asClassName : @ "GormDocument" ] ;
[ u decodeClassName : @ "GSNibItem"
asClassName : @ "GormObjectProxy" ] ;
[ u decodeClassName : @ "GSCustomView"
asClassName : @ "GormCustomView" ] ;
2005-04-17 16:14:12 +00:00
while ( ( subClassName = [ en nextObject ] ) ! = nil )
{
NSString * realClassName = [ substituteClasses objectForKey : subClassName ] ;
[ u decodeClassName : realClassName
asClassName : subClassName ] ;
}
2004-08-28 15:05:35 +00:00
[ GSClassSwapper setIsInInterfaceBuilder : YES ] ; // turn off custom classes .
2004-06-03 04:40:48 +00:00
c = [ u decodeObject ] ;
if ( c = = nil || [ c isKindOfClass : [ GSNibContainer class ] ] = = NO )
2002-10-31 15:00:17 +00:00
{
2005-02-05 14:11:57 +00:00
NSRunAlertPanel ( _ ( @ "Problem Loading" ) ,
_ ( @ "Could not unarchive document data" ) ,
2004-12-18 15:06:18 +00:00
_ ( @ "OK" ) , nil , nil ) ;
2004-06-03 04:40:48 +00:00
return nil ;
2002-10-31 15:00:17 +00:00
}
2004-08-28 15:05:35 +00:00
[ GSClassSwapper setIsInInterfaceBuilder : NO ] ; // turn on custom classes .
2004-06-03 04:40:48 +00:00
// retrieve the custom class data . . .
cc = [ [ c nameTable ] objectForKey : GSCustomClassMap ] ;
if ( cc = = nil )
2002-11-04 13:52:31 +00:00
{
2004-06-03 04:40:48 +00:00
cc = [ NSMutableDictionary dictionary ] ; // create an empty one .
[ [ c nameTable ] setObject : cc forKey : GSCustomClassMap ] ;
}
[ classManager setCustomClassMap : cc ] ;
NSDebugLog ( @ "cc = %@" , cc ) ;
NSDebugLog ( @ "customClasses = %@" , [ classManager customClassMap ] ) ;
// convert from old file format . . .
if ( isDir = = NO )
{
NSString * s ;
s = [ aFile stringByDeletingPathExtension ] ;
s = [ s stringByAppendingPathExtension : @ "classes" ] ;
if ( ! [ classManager loadCustomClasses : s ] )
2002-11-04 13:52:31 +00:00
{
2005-02-05 14:11:57 +00:00
NSRunAlertPanel ( _ ( @ "Problem Loading" ) ,
_ ( @ "Could not open the associated classes file.\n"
@ "You won't be able to edit connections on custom classes" ) ,
2004-12-18 15:06:18 +00:00
_ ( @ "OK" ) , nil , nil ) ;
2002-11-04 13:52:31 +00:00
}
}
2004-06-03 04:40:48 +00:00
else
2002-11-18 20:54:26 +00:00
{
2004-06-03 04:40:48 +00:00
NSString * s ;
s = [ aFile stringByAppendingPathComponent : @ "data.classes" ] ;
if ( ! [ classManager loadCustomClasses : s ] )
2002-11-18 20:54:26 +00:00
{
2005-02-05 14:11:57 +00:00
NSRunAlertPanel ( _ ( @ "Problem Loading" ) ,
_ ( @ "Could not open the associated classes file.\n"
@ "You won't be able to edit connections on custom classes" ) ,
2004-12-18 15:06:18 +00:00
_ ( @ "OK" ) , nil , nil ) ;
2004-06-03 04:40:48 +00:00
}
2004-07-12 04:16:09 +00:00
s = [ aFile stringByAppendingPathComponent : @ "data.info" ] ;
if ( ! [ filePrefsManager loadFromFile : s ] )
{
NSLog ( @ "Loading gorm without data.info file. Default settings will be assumed." ) ;
}
2004-11-04 02:49:23 +00:00
else
{
int version = [ filePrefsManager version ] ;
int currentVersion = [ GormFilePrefsManager currentVersion ] ;
if ( version > currentVersion )
{
int retval = NSRunAlertPanel ( _ ( @ "Gorm Build Mismatch" ) ,
_ ( @ "The file being loaded was created with a newer build, continue?" ) ,
_ ( @ "OK" ) ,
_ ( @ "Cancel" ) ,
2004-12-18 15:06:18 +00:00
nil ,
nil ) ;
2004-11-04 02:49:23 +00:00
if ( retval ! = NSAlertDefaultReturn )
{
return nil ;
}
}
}
2004-06-03 04:40:48 +00:00
}
[ classesView reloadData ] ;
/ *
* 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 = [ [ c nameTable ] objectForKey : @ "NSOwner" ] ;
if ( ownerClass )
[ filesOwner setClassName : ownerClass ] ;
[ [ c nameTable ] setObject : filesOwner forKey : @ "NSOwner" ] ;
[ [ c nameTable ] setObject : firstResponder forKey : @ "NSFirst" ] ;
/ * Iterate over the contents of nameTable and create the connections * /
nt = [ c nameTable ] ;
enumerator = [ [ c 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 ] ;
}
/ *
2005-06-04 11:46:43 +00:00
* If the GSNibContainer version is 0 , we need to add the top level objects
2004-07-12 04:16:09 +00:00
* to the list so that they can be properly processed .
2004-06-03 04:40:48 +00:00
* /
2004-06-30 05:22:25 +00:00
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 )
{
[ topLevelObjects addObject : obj ] ;
}
}
2004-07-12 04:16:09 +00:00
isOlderArchive = YES ;
2004-06-30 05:22:25 +00:00
}
2004-07-12 04:16:09 +00:00
/ *
* Now we merge the objects from the nib container into our own data
* structures , taking care not to overwrite our NSOwner and NSFirst .
* /
2004-06-03 04:40:48 +00:00
[ nt removeObjectForKey : @ "NSOwner" ] ;
[ nt removeObjectForKey : @ "NSFirst" ] ;
2004-06-29 03:27:37 +00:00
[ topLevelObjects addObjectsFromArray : [ [ c topLevelObjects ] allObjects ] ] ;
2004-06-03 04:40:48 +00:00
[ connections addObjectsFromArray : [ c connections ] ] ;
[ nameTable addEntriesFromDictionary : nt ] ;
[ self rebuildObjToNameMapping ] ;
2004-06-29 03:27:37 +00:00
2005-07-05 14:58:42 +00:00
/ *
* 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 ] ] )
{
isOlderArchive = YES ;
}
2004-06-30 05:22:25 +00:00
/ *
* repair the . gorm file , if needed .
* /
2004-06-03 04:40:48 +00:00
if ( repairFile = = YES )
{
[ self _repairFile ] ;
}
/ *
* set our new file name
* /
ASSIGN ( documentPath , aFile ) ;
[ window setTitleWithRepresentedFilename : documentPath ] ;
/ *
* read in all of the sounds in the . gorm wrapper and
* load them into the editor .
* /
dirEnumerator = [ mgr enumeratorAtPath : documentPath ] ;
if ( dirEnumerator )
{
NSString * file = nil ;
NSArray * fileTypes = [ NSSound soundUnfilteredFileTypes ] ;
while ( ( file = [ dirEnumerator nextObject ] ) )
{
if ( [ fileTypes containsObject : [ file pathExtension ] ] )
2002-11-18 20:54:26 +00:00
{
2004-06-03 04:40:48 +00:00
NSString * soundPath ;
NSDebugLog ( @ "Add the sound %@" , file ) ;
soundPath = [ documentPath stringByAppendingPathComponent : file ] ;
2005-01-04 04:52:46 +00:00
[ soundsView addObject : [ GormSound soundForPath : soundPath inWrapper : YES ] ] ;
2002-11-18 20:54:26 +00:00
}
}
}
2004-06-03 04:40:48 +00:00
/ *
* read in all of the images in the . gorm wrapper and
* load them into the editor .
* /
dirEnumerator = [ mgr enumeratorAtPath : documentPath ] ;
if ( dirEnumerator )
{
NSString * file = nil ;
NSArray * fileTypes = [ NSImage imageFileTypes ] ;
while ( ( file = [ dirEnumerator nextObject ] ) )
{
if ( [ fileTypes containsObject : [ file pathExtension ] ] )
{
NSString * imagePath ;
2004-12-07 05:23:00 +00:00
NSDebugLog ( @ "Add the image %@" , file ) ;
2004-06-03 04:40:48 +00:00
imagePath = [ documentPath stringByAppendingPathComponent : file ] ;
2005-01-04 04:52:46 +00:00
[ imagesView addObject : [ GormImage imageForPath : imagePath inWrapper : YES ] ] ;
2004-06-03 04:40:48 +00:00
}
}
}
NSDebugLog ( @ "nameTable = %@" , [ c nameTable ] ) ;
// awaken all elements after the load is completed .
enumerator = [ [ c nameTable ] keyEnumerator ] ;
while ( ( key = [ enumerator nextObject ] ) ! = nil )
{
id o = [ [ c nameTable ] objectForKey : key ] ;
if ( [ o respondsToSelector : @ selector ( awakeFromDocument : ) ] )
{
[ o awakeFromDocument : self ] ;
}
}
2004-06-24 05:30:22 +00:00
// reposition the loaded menu appropriately . . .
mainMenu = [ nameTable objectForKey : @ "NSMenu" ] ;
if ( mainMenu ! = nil )
{
NSRect frame = [ window frame ] ;
NSPoint origin = frame . origin ;
NSRect menuFrame = [ [ mainMenu window ] frame ] ;
// account for the height of the menu we ' re loading .
origin . y + = ( frame . size . height + menuFrame . size . height + 150 ) ;
// place the main menu appropriately . . .
[ [ mainMenu window ] setFrameTopLeftPoint : origin ] ;
}
2004-06-03 04:40:48 +00:00
// this is the last thing we should do . . .
[ nc postNotificationName : IBDidOpenDocumentNotification
object : self ] ;
2004-08-08 17:23:17 +00:00
// document opened . . .
isDocumentOpen = YES ;
2004-06-03 04:40:48 +00:00
// release the unarchiver . . now that we ' re all done . . .
RELEASE ( u ) ;
2002-11-18 20:54:26 +00:00
}
2004-06-03 04:40:48 +00:00
NS_HANDLER
2004-05-01 00:05:53 +00:00
{
2005-02-05 14:11:57 +00:00
NSRunAlertPanel ( _ ( @ "Problem Loading" ) ,
[ NSString stringWithFormat : @ "Failed to load file. Exception: %@" , [ localException reason ] ] ,
2004-12-18 15:06:18 +00:00
_ ( @ "OK" ) , nil , nil ) ;
2004-06-03 04:40:48 +00:00
return nil ; // This will cause the calling method to release the document .
2004-05-01 00:05:53 +00:00
}
2004-06-03 04:40:48 +00:00
NS_ENDHANDLER
2003-05-23 02:25:34 +00:00
2000-01-04 17:46:26 +00:00
return self ;
}
2005-04-11 20:42:33 +00:00
/ * *
2002-11-13 16:10:22 +00:00
* Build our reverse mapping information and other initialisation
* /
- ( void ) rebuildObjToNameMapping
{
NSEnumerator * enumerator ;
NSString * name ;
2004-06-29 03:27:37 +00:00
id o ;
2002-11-13 16:10:22 +00:00
2004-04-05 04:33:37 +00:00
NSDebugLog ( @ "------ Rebuilding object to name mapping..." ) ;
2002-11-13 16:10:22 +00:00
NSResetMapTable ( objToName ) ;
NSMapInsert ( objToName , ( void * ) filesOwner , ( void * ) @ "NSOwner" ) ;
NSMapInsert ( objToName , ( void * ) firstResponder , ( void * ) @ "NSFirst" ) ;
2004-04-05 02:12:28 +00:00
enumerator = [ [ nameTable allKeys ] objectEnumerator ] ;
2002-11-13 16:10:22 +00:00
while ( ( name = [ enumerator nextObject ] ) ! = nil )
{
2004-06-29 03:27:37 +00:00
id obj = [ nameTable objectForKey : name ] ;
2004-04-05 02:12:28 +00:00
2004-04-05 04:33:37 +00:00
NSDebugLog ( @ "%@ --> %@" , name , obj ) ;
2002-11-13 16:10:22 +00:00
2004-06-29 03:27:37 +00:00
NSMapInsert ( objToName , ( void * ) obj , ( void * ) name ) ;
if ( ( [ obj isKindOfClass : [ NSMenu class ] ] && [ name isEqual : @ "NSMenu" ] ) || [ obj isKindOfClass : [ NSWindow class ] ] )
2002-11-13 16:10:22 +00:00
{
[ [ self openEditorForObject : obj ] activate ] ;
}
2004-06-29 03:27:37 +00:00
}
// All of the entries in the items array are "top level items"
// which should be visible in the object ' s view .
enumerator = [ topLevelObjects objectEnumerator ] ;
while ( ( o = [ enumerator nextObject ] ) ! = nil )
{
[ objectsView addObject : o ] ;
2002-11-13 16:10:22 +00:00
}
}
2005-04-11 20:42:33 +00:00
/ * *
* This assumes we have an empty document to start with - the loaded
1999-12-08 15:04:57 +00:00
* document is merged in to it .
* /
- ( id ) openDocument : ( id ) sender
{
2000-01-04 12:37:00 +00:00
NSArray * fileTypes ;
1999-12-08 15:04:57 +00:00
NSOpenPanel * oPanel = [ NSOpenPanel openPanel ] ;
int result ;
2004-06-29 03:27:37 +00:00
NSString * pth = [ [ NSUserDefaults standardUserDefaults ]
objectForKey : @ "OpenDir" ] ;
2003-01-02 06:17:15 +00:00
fileTypes = [ NSArray arrayWithObjects : @ "gorm" , @ "gmodel" , nil ] ;
1999-12-08 15:04:57 +00:00
[ oPanel setAllowsMultipleSelection : NO ] ;
[ oPanel setCanChooseFiles : YES ] ;
[ oPanel setCanChooseDirectories : NO ] ;
2002-04-07 22:02:41 +00:00
result = [ oPanel runModalForDirectory : pth
1999-12-08 15:04:57 +00:00
file : nil
types : fileTypes ] ;
if ( result = = NSOKButton )
{
2004-06-29 03:27:37 +00:00
NSString * filename = [ oPanel filename ] ;
NSString * ext = [ filename pathExtension ] ;
2005-03-31 03:01:36 +00:00
BOOL uniqueName = [ ( id < Gorm > ) NSApp documentNameIsUnique : filename ] ;
2002-11-05 05:42:45 +00:00
2004-05-08 20:04:13 +00:00
if ( uniqueName )
2002-11-05 05:42:45 +00:00
{
2004-05-08 20:04:13 +00:00
[ [ NSUserDefaults standardUserDefaults ] setObject : [ oPanel directory ]
forKey : @ "OpenDir" ] ;
if ( [ ext isEqualToString : @ "gorm" ] || [ ext isEqualToString : @ "nib" ] )
{
return [ self loadDocument : filename ] ;
}
else if ( [ ext isEqualToString : @ "gmodel" ] )
{
return [ self openGModel : filename ] ;
}
2002-11-05 05:42:45 +00:00
}
2004-05-08 20:04:13 +00:00
else
2002-11-05 05:42:45 +00:00
{
2004-05-08 20:04:13 +00:00
// if we get this far , we didn ' t succeed . .
2005-02-05 14:11:57 +00:00
NSRunAlertPanel ( _ ( @ "Problem Loading" ) ,
_ ( @ "Attempted to load a model which is already opened." ) ,
2004-12-18 15:06:18 +00:00
_ ( @ "OK" ) , nil , nil ) ;
2002-11-05 05:42:45 +00:00
}
1999-12-08 15:04:57 +00:00
}
2004-05-08 20:04:13 +00:00
return nil ; / * Failed * /
1999-12-08 15:04:57 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Open the editor for anObject .
* /
1999-12-08 15:19:11 +00:00
- ( id < IBEditors > ) openEditorForObject : ( id ) anObject
{
1999-12-14 17:38:17 +00:00
id < IBEditors > e = [ self editorForObject : anObject create : YES ] ;
2002-08-14 00:01:42 +00:00
id < IBEditors , IBSelectionOwners > p = [ self parentEditorForEditor : e ] ;
1999-12-14 17:38:17 +00:00
2000-01-14 13:34:15 +00:00
if ( p ! = nil && p ! = objectsView )
1999-12-14 17:38:17 +00:00
{
[ self openEditorForObject : [ p editedObject ] ] ;
}
2004-05-02 11:39:58 +00:00
// prevent bringing front of menus before they ' ve been properly sized .
if ( [ anObject isKindOfClass : [ NSMenu class ] ] = = NO )
{
[ e orderFront ] ;
[ [ e window ] makeKeyAndOrderFront : self ] ;
}
1999-12-14 17:38:17 +00:00
return e ;
1999-12-08 15:19:11 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Return the parent editor for anEditor .
* /
2002-08-14 00:01:42 +00:00
- ( id < IBEditors , IBSelectionOwners > ) parentEditorForEditor : ( id < IBEditors > ) anEditor
1999-12-08 15:19:11 +00:00
{
1999-12-14 17:38:17 +00:00
NSArray * links ;
GormObjectToEditor * con ;
links = [ self connectorsForSource : anEditor
2002-08-14 00:01:42 +00:00
ofClass : [ GormEditorToParent class ] ] ;
1999-12-14 17:38:17 +00:00
con = [ links lastObject ] ;
return [ con destination ] ;
1999-12-08 15:19:11 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Return the parent of anObject .
* /
1999-12-08 15:04:57 +00:00
- ( id ) parentOfObject : ( id ) anObject
{
NSArray * old ;
id < IBConnectors > con ;
1999-12-13 17:01:35 +00:00
old = [ self connectorsForSource : anObject ofClass : [ NSNibConnector class ] ] ;
1999-12-08 15:04:57 +00:00
con = [ old lastObject ] ;
1999-12-13 17:01:35 +00:00
if ( [ con destination ] ! = filesOwner && [ con destination ] ! = firstResponder )
1999-12-08 15:04:57 +00:00
{
return [ con destination ] ;
}
return nil ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Paste objects of aType into the document from aPasteboard
* with parent as the parent of the objects .
* /
1999-12-08 15:04:57 +00:00
- ( NSArray * ) pasteType : ( NSString * ) aType
fromPasteboard : ( NSPasteboard * ) aPasteboard
parent : ( id ) parent
{
2000-01-14 13:34:15 +00:00
NSData * data ;
NSArray * objects ;
NSEnumerator * enumerator ;
1999-12-08 15:04:57 +00:00
NSPoint filePoint ;
NSPoint screenPoint ;
2002-03-01 14:42:15 +00:00
NSUnarchiver * u ;
1999-12-08 15:04:57 +00:00
2000-01-14 13:34:15 +00:00
data = [ aPasteboard dataForType : aType ] ;
if ( data = = nil )
{
2004-02-21 18:48:48 +00:00
NSDebugLog ( @ "Pasteboard %@ doesn't contain data of %@" , aPasteboard , aType ) ;
2000-01-14 13:34:15 +00:00
return nil ;
}
2002-03-01 14:42:15 +00:00
u = AUTORELEASE ( [ [ NSUnarchiver alloc ] initForReadingWithData : data ] ) ;
[ u decodeClassName : @ "GSCustomView"
asClassName : @ "GormCustomView" ] ;
objects = [ u decodeObject ] ;
2000-01-14 13:34:15 +00:00
enumerator = [ objects objectEnumerator ] ;
1999-12-14 19:55:18 +00:00
filePoint = [ window mouseLocationOutsideOfEventStream ] ;
screenPoint = [ window convertBaseToScreen : filePoint ] ;
1999-12-08 15:04:57 +00:00
2000-01-04 12:21:17 +00:00
/ *
2000-01-14 17:07:44 +00:00
* Windows and panels are a special case - for a multiple window paste ,
2000-01-04 12:21:17 +00:00
* the windows need to be positioned so they are not on top of each other .
* /
1999-12-08 15:04:57 +00:00
if ( [ aType isEqualToString : IBWindowPboardType ] = = YES )
{
NSWindow * win ;
while ( ( win = [ enumerator nextObject ] ) ! = nil )
{
[ win setFrameTopLeftPoint : screenPoint ] ;
2000-01-04 12:21:17 +00:00
screenPoint . x + = 10 ;
screenPoint . y - = 10 ;
1999-12-08 15:04:57 +00:00
}
}
2003-08-03 09:01:11 +00:00
else
{
NSEnumerator * enumerator = [ objects objectEnumerator ] ;
NSRect frame ;
2005-04-11 04:05:30 +00:00
id obj ;
2003-08-03 09:01:11 +00:00
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
2003-08-10 19:55:04 +00:00
{
2003-08-23 01:04:36 +00:00
// check to see if the object has a frame . If so , then
// modify it . If not , simply iterate to the next object
if ( [ obj respondsToSelector : @ selector ( frame ) ] )
2003-08-10 19:55:04 +00:00
{
2003-08-23 01:04:36 +00:00
frame = [ obj frame ] ;
frame . origin . x - = 6 ;
frame . origin . y - = 6 ;
[ obj setFrame : frame ] ;
2004-06-23 01:19:08 +00:00
RETAIN ( obj ) ;
2003-08-10 19:55:04 +00:00
}
}
2003-08-03 09:01:11 +00:00
}
1999-12-08 15:04:57 +00:00
[ self attachObjects : objects toParent : parent ] ;
[ self touch ] ;
return objects ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Remove aConnector from the connections array and send the
* notifications .
* /
1999-12-08 15:04:57 +00:00
- ( void ) removeConnector : ( id < IBConnectors > ) aConnector
{
2005-06-15 00:34:36 +00:00
NSNotificationCenter * nc = [ NSNotificationCenter defaultCenter ] ;
2005-04-17 01:48:49 +00:00
RETAIN ( aConnector ) ; // prevent it from being dealloc ' d until the notification is done .
2003-06-06 06:24:46 +00:00
// issue pre notification . .
2005-06-15 00:34:36 +00:00
[ nc postNotificationName : IBWillRemoveConnectorNotification
2005-04-17 01:48:49 +00:00
object : aConnector ] ;
2005-04-11 20:42:33 +00:00
2003-06-06 06:24:46 +00:00
// mark the document as changed .
[ self touch ] ;
2005-04-11 20:42:33 +00:00
// issue post notification . .
1999-12-08 15:04:57 +00:00
[ connections removeObjectIdenticalTo : aConnector ] ;
2003-05-23 02:25:34 +00:00
[ nc postNotificationName : IBDidRemoveConnectorNotification
2005-04-17 01:48:49 +00:00
object : aConnector ] ;
RELEASE ( aConnector ) ; // NOW we can dealloc it .
1999-12-08 15:04:57 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* The editor wants to give up the selection . Go through all the known
* editors ( with links in the connections array ) and try to find one
* that wants to take over the selection . Activate whatever editor we
* find ( if any ) .
* /
1999-12-08 15:19:11 +00:00
- ( void ) resignSelectionForEditor : ( id < IBEditors > ) editor
{
1999-12-14 17:38:17 +00:00
NSEnumerator * enumerator = [ connections objectEnumerator ] ;
Class editClass = [ GormObjectToEditor class ] ;
id < IBConnectors > c ;
while ( ( c = [ enumerator nextObject ] ) ! = nil )
{
if ( [ c class ] = = editClass )
{
id < IBEditors > e = [ c destination ] ;
if ( e ! = editor && [ e wantsSelection ] = = YES )
{
1999-12-15 11:12:52 +00:00
[ e activate ] ;
2000-01-04 12:21:17 +00:00
[ self setSelectionFromEditor : e ] ;
2000-01-04 16:25:39 +00:00
return ;
1999-12-14 17:38:17 +00:00
}
}
}
2000-01-04 16:25:39 +00:00
/ *
* No editor available to take the selection - set a nil owner .
* /
[ self setSelectionFromEditor : nil ] ;
1999-12-08 15:19:11 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Creates a blank document depending on the value of type .
* If type is "Application" , "Inspector" or "Palette" it creates
* an appropriate blank document for the user to start with .
* /
2000-01-13 21:19:03 +00:00
- ( void ) setupDefaults : ( NSString * ) type
{
if ( hasSetDefaults = = YES )
{
return ;
}
hasSetDefaults = YES ;
if ( [ type isEqual : @ "Application" ] = = YES )
{
2002-04-07 22:02:41 +00:00
NSMenu * aMenu ;
2000-01-13 21:19:03 +00:00
NSWindow * aWindow ;
2004-06-24 05:30:22 +00:00
NSRect winFrame = [ window frame ] ;
NSPoint origin = winFrame . origin ;
2000-01-13 21:19:03 +00:00
NSRect frame = [ [ NSScreen mainScreen ] frame ] ;
unsigned style = NSTitledWindowMask | NSClosableWindowMask
| NSResizableWindowMask | NSMiniaturizableWindowMask ;
2004-06-24 05:30:22 +00:00
origin . y + = ( winFrame . size . height + 150 ) ;
2002-04-07 22:02:41 +00:00
if ( [ NSMenu respondsToSelector : @ selector ( allocSubstitute ) ] )
{
aMenu = [ [ NSMenu allocSubstitute ] init ] ;
}
else
{
aMenu = [ [ NSMenu alloc ] init ] ;
}
if ( [ NSWindow respondsToSelector : @ selector ( allocSubstitute ) ] )
{
aWindow = [ [ NSWindow allocSubstitute ]
initWithContentRect : NSMakeRect ( 0 , 0 , 600 , 400 )
styleMask : style
backing : NSBackingStoreRetained
defer : NO ] ;
}
else
{
aWindow = [ [ NSWindow alloc ]
initWithContentRect : NSMakeRect ( 0 , 0 , 600 , 400 )
styleMask : style
backing : NSBackingStoreRetained
defer : NO ] ;
}
2000-01-13 21:19:03 +00:00
[ aWindow setFrameTopLeftPoint :
NSMakePoint ( 220 , frame . size . height -100 ) ] ;
2003-05-24 12:40:54 +00:00
[ aWindow setTitle : _ ( @ "My Window" ) ] ;
2000-01-14 17:26:25 +00:00
[ self setName : @ "My Window" forObject : aWindow ] ;
2000-01-13 21:19:03 +00:00
[ self attachObject : aWindow toParent : nil ] ;
2000-01-14 17:07:44 +00:00
[ self setObject : aWindow isVisibleAtLaunch : YES ] ;
2000-01-13 21:19:03 +00:00
2003-05-24 12:40:54 +00:00
[ aMenu setTitle : _ ( @ "Main Menu" ) ] ;
[ aMenu addItemWithTitle : _ ( @ "Hide" )
2000-01-13 21:19:03 +00:00
action : @ selector ( hide : )
keyEquivalent : @ "h" ] ;
2003-05-24 12:40:54 +00:00
[ aMenu addItemWithTitle : _ ( @ "Quit" )
2000-01-13 21:19:03 +00:00
action : @ selector ( terminate : )
2002-04-07 22:02:41 +00:00
keyEquivalent : @ "q" ] ;
2004-06-29 03:27:37 +00:00
// the first menu attached becomes the main menu .
[ self attachObject : aMenu toParent : nil ] ;
2004-06-24 05:30:22 +00:00
[ [ aMenu window ] setFrameTopLeftPoint : origin ] ;
2000-01-13 21:19:03 +00:00
}
2000-01-14 17:07:44 +00:00
else if ( [ type isEqual : @ "Inspector" ] = = YES )
{
NSWindow * aWindow ;
NSRect frame = [ [ NSScreen mainScreen ] frame ] ;
unsigned style = NSTitledWindowMask | NSClosableWindowMask ;
2004-05-10 12:08:49 +00:00
if ( [ NSWindow respondsToSelector : @ selector ( allocSubstitute ) ] )
{
aWindow = [ [ NSWindow allocSubstitute ]
initWithContentRect : NSMakeRect ( 0 , 0 , IVW , IVH )
styleMask : style
backing : NSBackingStoreRetained
defer : NO ] ;
}
else
{
aWindow = [ [ NSWindow alloc ]
initWithContentRect : NSMakeRect ( 0 , 0 , IVW , IVH )
styleMask : style
backing : NSBackingStoreRetained
defer : NO ] ;
}
2000-01-14 17:07:44 +00:00
[ aWindow setFrameTopLeftPoint :
2004-05-13 05:13:36 +00:00
NSMakePoint ( 220 , frame . size . height -100 ) ] ;
2003-05-24 12:40:54 +00:00
[ aWindow setTitle : _ ( @ "Inspector Window" ) ] ;
2000-01-14 17:26:25 +00:00
[ self setName : @ "InspectorWin" forObject : aWindow ] ;
2000-01-14 17:07:44 +00:00
[ self attachObject : aWindow toParent : nil ] ;
}
else if ( [ type isEqual : @ "Palette" ] = = YES )
{
NSWindow * aWindow ;
NSRect frame = [ [ NSScreen mainScreen ] frame ] ;
unsigned style = NSTitledWindowMask | NSClosableWindowMask ;
2004-05-10 12:08:49 +00:00
if ( [ NSWindow respondsToSelector : @ selector ( allocSubstitute ) ] )
{
aWindow = [ [ NSWindow allocSubstitute ]
2004-08-04 04:52:43 +00:00
initWithContentRect : NSMakeRect ( 0 , 0 , 272 , 160 )
2004-05-10 12:08:49 +00:00
styleMask : style
backing : NSBackingStoreRetained
defer : NO ] ;
}
else
{
aWindow = [ [ NSWindow alloc ]
2004-08-04 04:52:43 +00:00
initWithContentRect : NSMakeRect ( 0 , 0 , 272 , 160 )
2004-05-10 12:08:49 +00:00
styleMask : style
backing : NSBackingStoreRetained
defer : NO ] ;
}
2000-01-14 17:07:44 +00:00
[ aWindow setFrameTopLeftPoint :
2004-05-13 05:13:36 +00:00
NSMakePoint ( 220 , frame . size . height -100 ) ] ;
2003-05-24 12:40:54 +00:00
[ aWindow setTitle : _ ( @ "Palette Window" ) ] ;
2000-01-14 17:26:25 +00:00
[ self setName : @ "PaletteWin" forObject : aWindow ] ;
2000-01-14 17:07:44 +00:00
[ self attachObject : aWindow toParent : nil ] ;
}
2005-02-13 14:30:55 +00:00
[ self touch ] ;
2000-01-13 21:19:03 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Set aName for object in the document . If aName is nil ,
* a name is automatically created for object .
* /
1999-12-08 15:04:57 +00:00
- ( void ) setName : ( NSString * ) aName forObject : ( id ) object
{
2005-04-28 12:50:50 +00:00
id oldObject = nil ;
NSString * oldName = nil ;
2004-03-04 06:02:24 +00:00
NSMutableDictionary * cc = [ classManager customClassMap ] ;
2005-04-28 12:50:50 +00:00
NSString * className = nil ;
1999-12-08 15:04:57 +00:00
if ( object = = nil )
{
2004-02-21 18:48:48 +00:00
NSDebugLog ( @ "Attempt to set name for nil object" ) ;
1999-12-08 15:04:57 +00:00
return ;
}
2004-07-21 01:49:07 +00:00
1999-12-08 15:04:57 +00:00
if ( aName = = nil )
{
/ *
* No name given - so we must generate one unless we already have one .
* /
oldName = [ self nameForObject : object ] ;
if ( oldName = = nil )
{
NSString * base ;
unsigned i = 0 ;
/ *
* Generate a sensible name for the object based on its class .
* /
2001-05-08 09:43:11 +00:00
if ( [ object isKindOfClass : [ GSNibItem class ] ] )
{
// use the actual class name for proxies
base = [ ( id ) object className ] ;
}
else
{
base = NSStringFromClass ( [ object class ] ) ;
}
1999-12-08 15:04:57 +00:00
if ( [ base hasPrefix : @ "NS" ] || [ base hasPrefix : @ "GS" ] )
{
base = [ base substringFromIndex : 2 ] ;
}
aName = base ;
while ( [ nameTable objectForKey : aName ] ! = nil )
{
aName = [ base stringByAppendingFormat : @ "%u" , + + i ] ;
}
}
else
{
2005-04-11 20:42:33 +00:00
return ; / * Already named . . . nothing to do * /
1999-12-08 15:04:57 +00:00
}
}
2005-04-28 12:50:50 +00:00
else // user supplied a name . . .
1999-12-08 15:04:57 +00:00
{
oldObject = [ nameTable objectForKey : aName ] ;
if ( oldObject ! = nil )
{
2004-02-21 18:48:48 +00:00
NSDebugLog ( @ "Attempt to re-use name '%@'" , aName ) ;
1999-12-08 15:04:57 +00:00
return ;
}
oldName = [ self nameForObject : object ] ;
if ( oldName ! = nil )
{
if ( [ oldName isEqual : aName ] = = YES )
{
2005-04-11 20:42:33 +00:00
return ; / * Already have this name . . . nothing to do * /
1999-12-08 15:04:57 +00:00
}
2000-02-25 17:26:57 +00:00
[ nameTable removeObjectForKey : oldName ] ;
1999-12-08 15:04:57 +00:00
NSMapRemove ( objToName , ( void * ) object ) ;
}
}
2005-04-11 20:42:33 +00:00
// add it to the dictionary .
2004-07-27 06:20:45 +00:00
[ nameTable setObject : object forKey : aName ] ;
2005-04-11 20:42:33 +00:00
NSMapInsert ( objToName , ( void * ) object , ( void * ) aName ) ;
1999-12-08 15:04:57 +00:00
if ( oldName ! = nil )
{
2005-04-28 12:50:50 +00:00
RETAIN ( oldName ) ; // hold on to this temporarily . . .
1999-12-08 15:04:57 +00:00
[ nameTable removeObjectForKey : oldName ] ;
}
1999-12-22 10:13:18 +00:00
if ( [ objectsView containsObject : object ] = = YES )
{
[ objectsView refreshCells ] ;
}
2004-03-04 06:02:24 +00:00
// check the custom classes map and replace the appropriate
// object , if a mapping exists .
if ( cc ! = nil )
{
className = [ cc objectForKey : oldName ] ;
if ( className ! = nil )
{
[ cc removeObjectForKey : oldName ] ;
2005-04-11 20:42:33 +00:00
[ cc setObject : className forKey : aName ] ;
2004-03-04 06:02:24 +00:00
}
}
2005-04-28 12:50:50 +00:00
// release oldName , if we get to this point .
if ( oldName ! = nil )
{
RELEASE ( oldName ) ;
}
1999-12-08 15:04:57 +00:00
}
2005-04-11 20:42:33 +00:00
/ * *
* Add object to the visible at launch list .
* /
2000-01-03 11:00:14 +00:00
- ( void ) setObject : ( id ) anObject isVisibleAtLaunch : ( BOOL ) flag
{
NSMutableArray * a = [ nameTable objectForKey : @ "NSVisible" ] ;
if ( flag = = YES )
{
if ( a = = nil )
{
2005-06-17 04:41:24 +00:00
a = [ [ NSMutableArray alloc ] init ] ;
2000-01-03 11:00:14 +00:00
[ nameTable setObject : a forKey : @ "NSVisible" ] ;
2003-05-10 17:34:45 +00:00
RELEASE ( a ) ;
2000-01-03 11:00:14 +00:00
}
if ( [ a containsObject : anObject ] = = NO )
{
[ a addObject : anObject ] ;
}
}
else
{
[ a removeObject : anObject ] ;
}
}
2005-04-11 20:42:33 +00:00
/ * *
* Return YES , if anObject is visible at launch time .
* /
- ( BOOL ) objectIsVisibleAtLaunch : ( id ) anObject
{
return [ [ nameTable objectForKey : @ "NSVisible" ] containsObject : anObject ] ;
}
/ * *
* Add anObject to the deferred list .
* /
2003-01-16 04:09:07 +00:00
- ( void ) setObject : ( id ) anObject isDeferred : ( BOOL ) flag
2002-10-13 06:04:05 +00:00
{
2003-01-16 04:09:07 +00:00
NSMutableArray * a = [ nameTable objectForKey : @ "NSDeferred" ] ;
2002-10-13 06:04:05 +00:00
if ( flag = = YES )
{
2003-01-16 04:09:07 +00:00
if ( a = = nil )
{
2005-06-17 04:41:24 +00:00
a = [ [ NSMutableArray alloc ] init ] ;
2003-01-16 04:09:07 +00:00
[ nameTable setObject : a forKey : @ "NSDeferred" ] ;
RELEASE ( a ) ;
}
if ( [ a containsObject : anObject ] = = NO )
2002-10-13 06:04:05 +00:00
{
2003-01-16 04:09:07 +00:00
[ a addObject : anObject ] ;
2002-10-13 06:04:05 +00:00
}
}
else
{
2003-01-16 04:09:07 +00:00
[ a removeObject : anObject ] ;
2002-10-13 06:04:05 +00:00
}
}
2005-04-11 20:42:33 +00:00
/ * *
* Return YES , if the anObject is in the deferred list .
* /
2003-01-16 04:09:07 +00:00
- ( BOOL ) objectIsDeferred : ( id ) anObject
2002-10-13 06:04:05 +00:00
{
2003-01-16 04:09:07 +00:00
return [ [ nameTable objectForKey : @ "NSDeferred" ] containsObject : anObject ] ;
2002-10-13 06:04:05 +00:00
}
2003-09-28 23:31:35 +00:00
// windows / services menus . . .
2005-04-11 20:42:33 +00:00
/ * *
* Set the windows menu .
* /
2003-09-28 23:31:35 +00:00
- ( void ) setWindowsMenu : ( NSMenu * ) anObject
{
if ( anObject ! = nil )
{
[ nameTable setObject : anObject forKey : @ "NSWindowsMenu" ] ;
}
else
{
[ nameTable removeObjectForKey : @ "NSWindowsMenu" ] ;
}
}
2005-04-11 20:42:33 +00:00
/ * *
* return the windows menu .
* /
2003-09-28 23:31:35 +00:00
- ( NSMenu * ) windowsMenu
{
return [ nameTable objectForKey : @ "NSWindowsMenu" ] ;
}
2005-04-11 20:42:33 +00:00
/ * *
* Set the object that will be the services menu in the app .
* /
2003-09-28 23:31:35 +00:00
- ( void ) setServicesMenu : ( NSMenu * ) anObject
{
if ( anObject ! = nil )
{
[ nameTable setObject : anObject forKey : @ "NSServicesMenu" ] ;
}
else
{
[ nameTable removeObjectForKey : @ "NSServicesMenu" ] ;
}
}
2005-04-11 20:42:33 +00:00
/ * *
* Return the object that will be the services menu .
* /
2003-09-28 23:31:35 +00:00
- ( NSMenu * ) servicesMenu
{
return [ nameTable objectForKey : @ "NSServicesMenu" ] ;
}
2005-02-13 09:40:12 +00:00
/ * *
2000-01-04 17:46:26 +00:00
* To revert to a saved version , we actually load a new document and
* close the original document , returning the id of the new document .
* /
- ( id ) revertDocument : ( id ) sender
{
2005-06-17 04:41:24 +00:00
GormDocument * reverted = AUTORELEASE ( [ [ GormDocument alloc ] init ] ) ;
2000-01-04 17:46:26 +00:00
if ( [ reverted loadDocument : documentPath ] ! = nil )
{
NSRect frame = [ window frame ] ;
[ window close ] ;
[ [ reverted window ] setFrame : frame display : YES ] ;
return reverted ;
}
return nil ;
}
2005-02-13 09:40:12 +00:00
/ * *
* Save the document . If this is called when documentPath is nil ,
* then saveGormDocument : will call it to define the path .
* /
2003-05-20 03:57:37 +00:00
- ( BOOL ) saveAsDocument : ( id ) sender
1999-12-08 15:04:57 +00:00
{
2000-01-04 12:21:17 +00:00
NSSavePanel * sp ;
int result ;
1999-12-08 15:04:57 +00:00
sp = [ NSSavePanel savePanel ] ;
2003-01-02 06:17:15 +00:00
[ sp setRequiredFileType : @ "gorm" ] ;
1999-12-08 15:04:57 +00:00
result = [ sp runModalForDirectory : NSHomeDirectory ( ) file : @ "" ] ;
if ( result = = NSOKButton )
{
NSFileManager * mgr = [ NSFileManager defaultManager ] ;
NSString * path = [ sp filename ] ;
if ( [ path isEqual : documentPath ] = = NO
&& [ mgr fileExistsAtPath : path ] = = YES )
{
2002-11-12 21:44:48 +00:00
/ * NSSavePanel has already asked if it ' s ok to replace * /
NSString * bPath = [ path stringByAppendingString : @ "~" ] ;
[ mgr removeFileAtPath : bPath handler : nil ] ;
[ mgr movePath : path toPath : bPath handler : nil ] ;
1999-12-08 15:04:57 +00:00
}
2004-05-08 15:42:27 +00:00
// set the path . . .
ASSIGN ( documentPath , path ) ;
2005-02-06 15:38:10 +00:00
return [ self saveGormDocument : sender ] ;
1999-12-08 15:04:57 +00:00
}
2003-05-20 03:57:37 +00:00
return NO ;
1999-12-08 15:04:57 +00:00
}
2005-02-13 09:40:12 +00:00
/ * *
* 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 .
* /
2003-08-23 01:04:36 +00:00
- ( void ) _replaceObjectsWithTemplates : ( NSArchiver * ) archiver
{
GormClassManager * cm = [ self classManager ] ;
2005-06-04 11:46:43 +00:00
NSEnumerator * en = [ [ self nameTable ] keyEnumerator ] ;
2003-08-23 01:04:36 +00:00
id key = nil ;
2003-10-08 05:00:21 +00:00
2005-06-04 11:46:43 +00:00
// loop through all custom objects and windows
2003-08-23 01:04:36 +00:00
while ( ( key = [ en nextObject ] ) ! = nil )
{
2005-06-04 11:46:43 +00:00
id customClass = [ cm customClassForName : key ] ;
2003-10-08 05:00:21 +00:00
id object = [ self objectForName : key ] ;
2005-06-04 11:46:43 +00:00
id template = nil ;
if ( customClass ! = nil )
{
NSString * superClass = [ cm nonCustomSuperClassOf : customClass ] ;
template = [ GSTemplateFactory templateForObject : object
withClassName : customClass
withSuperClassName : superClass ] ;
}
else if ( [ object isKindOfClass : [ NSWindow class ] ] )
2003-10-08 05:00:21 +00:00
{
2005-06-04 11:46:43 +00:00
template = [ GSTemplateFactory templateForObject : object
withClassName : [ object className ]
withSuperClassName : [ object className ] ] ;
2003-10-08 05:00:21 +00:00
}
2005-06-04 11:46:43 +00:00
// 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 : [ self 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 ] ;
}
2003-08-23 01:04:36 +00:00
}
}
2005-02-13 09:40:12 +00:00
/ * *
* Save the document . This method creates the directory and the files needed
* to comprise the . gorm package .
* /
2003-05-20 03:57:37 +00:00
- ( BOOL ) saveGormDocument : ( id ) sender
1999-12-08 15:04:57 +00:00
{
1999-12-08 15:19:11 +00:00
NSNotificationCenter * nc = [ NSNotificationCenter defaultCenter ] ;
1999-12-15 11:12:52 +00:00
BOOL archiveResult ;
2001-05-08 09:43:11 +00:00
NSArchiver * archiver ;
NSMutableData * archiverData ;
2002-10-31 15:00:17 +00:00
NSString * gormPath ;
NSString * classesPath ;
2004-07-12 04:16:09 +00:00
NSString * infoPath ;
2002-10-31 15:00:17 +00:00
NSFileManager * mgr = [ NSFileManager defaultManager ] ;
BOOL isDir ;
BOOL fileExists ;
2004-07-01 00:53:42 +00:00
int retval ;
2005-04-17 16:14:12 +00:00
GormPalettesManager * palettesManager = [ ( id < Gorm > ) NSApp palettesManager ] ;
NSDictionary * substituteClasses = [ palettesManager substituteClasses ] ;
NSEnumerator * en = [ substituteClasses keyEnumerator ] ;
NSString * subClassName = nil ;
2000-01-04 17:46:26 +00:00
if ( documentPath = = nil )
1999-12-08 15:04:57 +00:00
{
2004-07-12 04:16:09 +00:00
// if no path has been defined . . . define one .
return ( [ self saveAsDocument : sender ] ) ;
1999-12-08 15:04:57 +00:00
}
1999-12-08 15:19:11 +00:00
2004-07-01 00:53:42 +00:00
// Warn the user about possible incompatibility .
2004-07-12 04:16:09 +00:00
// TODO : Remove after the next release of GUI .
if ( isOlderArchive && [ filePrefsManager isLatest ] )
2004-07-01 00:53:42 +00:00
{
retval = NSRunAlertPanel ( _ ( @ "Compatibility Warning" ) ,
2005-06-04 11:46:43 +00:00
_ ( @ "Saving will update this gorm to the latest version, which is not compatible with GNUstep's gui 0.9.5 (or earlier) Release or CVS prior to June 2 2005." ) ,
2004-07-01 00:53:42 +00:00
_ ( @ "Save" ) ,
_ ( @ "Don't Save" ) , nil , nil ) ;
if ( retval ! = NSAlertDefaultReturn )
{
return NO ;
}
else
{
// we ' re saving anyway . . . set to new value .
2004-07-12 04:16:09 +00:00
isOlderArchive = NO ;
2004-07-01 00:53:42 +00:00
}
}
1999-12-08 15:19:11 +00:00
[ nc postNotificationName : IBWillSaveDocumentNotification
object : self ] ;
2000-01-03 11:00:14 +00:00
[ self beginArchiving ] ;
1999-12-15 11:12:52 +00:00
2002-10-31 15:00:17 +00:00
// set up the necessary paths . . .
gormPath = [ documentPath stringByAppendingPathComponent : @ "objects.gorm" ] ;
2002-11-18 06:15:06 +00:00
classesPath = [ documentPath stringByAppendingPathComponent : @ "data.classes" ] ;
2004-07-12 04:16:09 +00:00
infoPath = [ documentPath stringByAppendingPathComponent : @ "data.info" ] ;
2001-05-08 09:43:11 +00:00
archiverData = [ NSMutableData dataWithCapacity : 0 ] ;
archiver = [ [ NSArchiver alloc ] initForWritingWithMutableData : archiverData ] ;
2002-11-18 06:15:06 +00:00
/ * Special gorm classes to their archive equivalents . * /
2005-06-04 11:46:43 +00:00
// NOTE : GSNibContainer replaces GormDocument using classforCoder
2002-11-18 06:15:06 +00:00
[ archiver encodeClassName : @ "GormObjectProxy"
intoClassName : @ "GSNibItem" ] ;
2002-03-31 15:59:18 +00:00
[ archiver encodeClassName : @ "GormCustomView"
2002-11-18 06:15:06 +00:00
intoClassName : @ "GSCustomView" ] ;
2005-04-17 16:14:12 +00:00
while ( ( subClassName = [ en nextObject ] ) ! = nil )
{
NSString * realClassName = [ substituteClasses objectForKey : subClassName ] ;
[ archiver encodeClassName : subClassName
intoClassName : realClassName ] ;
}
2002-10-13 06:04:05 +00:00
2003-08-23 01:04:36 +00:00
[ self _replaceObjectsWithTemplates : archiver ] ;
2003-05-23 02:25:34 +00:00
2001-05-08 09:43:11 +00:00
[ archiver encodeRootObject : self ] ;
2003-08-28 04:32:41 +00:00
NSDebugLog ( @ "nameTable = %@" , nameTable ) ;
NSDebugLog ( @ "customClasses = %@" , [ classManager customClassMap ] ) ;
2003-08-24 17:10:05 +00:00
2002-10-31 15:00:17 +00:00
fileExists = [ mgr fileExistsAtPath : documentPath isDirectory : & isDir ] ;
2003-02-13 13:32:59 +00:00
if ( fileExists )
2002-10-31 15:00:17 +00:00
{
2003-02-13 13:32:59 +00:00
if ( isDir = = NO )
2002-10-31 15:00:17 +00:00
{
2003-02-13 13:32:59 +00:00
NSString * saveFilePath ;
2002-10-31 15:00:17 +00:00
2003-02-13 13:32:59 +00:00
saveFilePath = [ documentPath stringByAppendingPathExtension : @ "save" ] ;
2002-10-31 15:00:17 +00:00
// move the old file to something . . .
2003-02-13 13:32:59 +00:00
if ( ! [ mgr movePath : documentPath toPath : saveFilePath handler : nil ] )
2002-10-31 15:00:17 +00:00
{
2004-02-21 18:48:48 +00:00
NSDebugLog ( @ "Error moving old %@ file to %@" ,
2003-02-13 13:32:59 +00:00
documentPath , saveFilePath ) ;
2002-10-31 15:00:17 +00:00
}
// create the new directory . .
2003-02-13 13:32:59 +00:00
archiveResult = [ mgr createDirectoryAtPath : documentPath
attributes : nil ] ;
2002-10-31 15:00:17 +00:00
}
else
{
// set to yes since the directory is already present .
archiveResult = YES ;
}
}
else
{
// create the directory . . .
archiveResult = [ mgr createDirectoryAtPath : documentPath attributes : nil ] ;
}
2003-07-20 20:26:20 +00:00
RELEASE ( archiver ) ; // We ' re done with the archiver here . .
2002-10-31 15:00:17 +00:00
2003-02-13 13:32:59 +00:00
if ( archiveResult )
2002-10-31 15:00:17 +00:00
{
// save the data . . .
archiveResult = [ archiverData writeToFile : gormPath atomically : YES ] ;
if ( archiveResult )
{
// save the custom classes . . and we ' re done . . .
archiveResult = [ classManager saveToFile : classesPath ] ;
2004-07-12 04:16:09 +00:00
// save the file prefs metadata . . .
if ( archiveResult )
{
archiveResult = [ filePrefsManager saveToFile : infoPath ] ;
}
2002-11-04 13:52:31 +00:00
2005-01-04 04:52:46 +00:00
//
// 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 .
//
2003-02-13 13:32:59 +00:00
if ( archiveResult )
2002-11-04 13:52:31 +00:00
{
2004-05-15 15:39:57 +00:00
NSArray * sounds = [ soundsView objects ] ;
NSArray * images = [ imagesView objects ] ;
2005-03-02 02:27:55 +00:00
NSArray * resources = [ sounds arrayByAddingObjectsFromArray : images ] ;
2002-11-04 13:52:31 +00:00
id object = nil ;
2005-03-02 02:27:55 +00:00
NSEnumerator * en = [ resources objectEnumerator ] ;
2003-02-13 13:32:59 +00:00
while ( ( object = [ en nextObject ] ) ! = nil )
2002-11-04 13:52:31 +00:00
{
2005-03-02 02:27:55 +00:00
if ( ! [ object isSystemResource ] )
2002-11-04 13:52:31 +00:00
{
2005-03-02 02:27:55 +00:00
NSString * rscPath ;
NSString * path = [ object path ] ;
2004-05-15 15:39:57 +00:00
BOOL copied = NO ;
2005-03-02 02:27:55 +00:00
rscPath = [ documentPath stringByAppendingPathComponent :
[ path lastPathComponent ] ] ;
if ( ! [ path isEqualToString : rscPath ] )
2004-05-15 15:39:57 +00:00
{
copied = [ mgr copyPath : path
2005-03-02 02:27:55 +00:00
toPath : rscPath
2004-05-15 15:39:57 +00:00
handler : nil ] ;
2005-01-04 04:52:46 +00:00
if ( copied )
{
[ object setInWrapper : YES ] ;
2005-03-02 02:27:55 +00:00
[ object setPath : rscPath ] ;
2005-01-04 04:52:46 +00:00
}
2004-05-15 15:39:57 +00:00
}
else
{
// mark as copied if paths are equal . . .
copied = YES ;
2005-01-04 04:52:46 +00:00
[ object setInWrapper : YES ] ;
2004-05-15 15:39:57 +00:00
}
if ( ! copied )
{
2005-03-02 02:27:55 +00:00
NSDebugLog ( @ "Could not find resource at path %@" , object ) ;
2004-05-15 15:39:57 +00:00
}
2002-11-04 13:52:31 +00:00
}
}
}
2002-10-31 15:00:17 +00:00
}
}
1999-12-15 11:12:52 +00:00
2003-07-15 04:20:09 +00:00
[ self endArchiving ] ;
1999-12-15 11:12:52 +00:00
if ( archiveResult = = NO )
1999-12-08 15:04:57 +00:00
{
2005-02-05 14:11:57 +00:00
NSRunAlertPanel ( _ ( @ "Problem Saving" ) ,
_ ( @ "Could not save document" ) ,
2004-12-18 15:06:18 +00:00
_ ( @ "OK" ) , nil , nil ) ;
1999-12-08 15:04:57 +00:00
}
2003-04-18 05:40:25 +00:00
else
{
2005-02-06 15:38:10 +00:00
// mark the file as not edited .
2003-04-18 05:40:25 +00:00
[ window setDocumentEdited : NO ] ;
[ window setTitleWithRepresentedFilename : documentPath ] ;
1999-12-15 11:12:52 +00:00
2005-02-06 15:38:10 +00:00
// notify everyone of the save .
2003-04-18 05:40:25 +00:00
[ nc postNotificationName : IBDidSaveDocumentNotification
object : self ] ;
}
2003-05-20 03:57:37 +00:00
return YES ;
1999-12-08 15:04:57 +00:00
}
2005-02-13 09:40:12 +00:00
/ * *
* Marks this document as the currently active document . The active document is
* the one being edited by the user .
* /
1999-12-08 15:04:57 +00:00
- ( void ) setDocumentActive : ( BOOL ) flag
{
2004-08-08 17:23:17 +00:00
if ( flag ! = isActive && isDocumentOpen )
1999-12-08 15:04:57 +00:00
{
2000-01-04 16:25:39 +00:00
NSEnumerator * enumerator ;
id obj ;
2005-01-31 06:32:16 +00:00
// stop all connection activities .
2005-03-31 03:01:36 +00:00
[ ( id < Gorm > ) NSApp stopConnecting ] ;
2005-01-31 06:32:16 +00:00
2000-01-04 16:25:39 +00:00
enumerator = [ nameTable objectEnumerator ] ;
if ( flag = = YES )
1999-12-08 15:04:57 +00:00
{
2004-05-01 00:05:53 +00:00
GormDocument * document = ( GormDocument * ) [ ( id < IB > ) NSApp activeDocument ] ;
// set the current document active and unset the old one .
[ document setDocumentActive : NO ] ;
2000-01-04 16:25:39 +00:00
isActive = YES ;
2004-05-01 00:05:53 +00:00
// display everything .
2000-01-04 16:25:39 +00:00
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
1999-12-08 15:04:57 +00:00
{
2004-05-01 00:05:53 +00:00
NSString * name = [ document nameForObject : obj ] ;
2000-01-04 16:25:39 +00:00
if ( [ obj isKindOfClass : [ NSWindow class ] ] = = YES )
{
[ obj orderFront : self ] ;
}
2004-05-01 00:05:53 +00:00
else if ( [ obj isKindOfClass : [ NSMenu class ] ] &&
[ name isEqual : @ "NSMenu" ] = = YES )
2000-01-04 16:25:39 +00:00
{
[ obj display ] ;
}
1999-12-08 15:04:57 +00:00
}
2004-06-03 22:37:14 +00:00
//
// Reset the selection to the current selection held by the current
// selection owner of this document when the document becomes active .
// This allows the app to switch to the correct inspector when the new
// document is selected .
//
[ self setSelectionFromEditor : lastEditor ] ;
1999-12-08 15:04:57 +00:00
}
2000-01-04 16:25:39 +00:00
else
1999-12-08 15:04:57 +00:00
{
2000-01-04 16:25:39 +00:00
isActive = NO ;
while ( ( obj = [ enumerator nextObject ] ) ! = nil )
1999-12-08 15:04:57 +00:00
{
2000-01-04 16:25:39 +00:00
if ( [ obj isKindOfClass : [ NSWindow class ] ] = = YES )
{
[ obj orderOut : self ] ;
}
2004-05-02 11:39:58 +00:00
else if ( [ obj isKindOfClass : [ NSMenu class ] ] = = YES &&
[ [ self nameForObject : obj ] isEqual : @ "NSMenu" ] = = YES )
2000-01-04 16:25:39 +00:00
{
[ obj close ] ;
}
1999-12-08 15:04:57 +00:00
}
2005-01-31 06:32:16 +00:00
[ self setSelectionFromEditor : nil ] ;
1999-12-08 15:04:57 +00:00
}
}
}
2005-07-05 14:58:42 +00:00
/ * *
* Sets the current selection from the given editor . This method
* causes the inspector to refresh with the proper object .
* /
1999-12-08 15:19:11 +00:00
- ( void ) setSelectionFromEditor : ( id < IBEditors > ) anEditor
{
1999-12-14 17:38:17 +00:00
NSNotificationCenter * nc = [ NSNotificationCenter defaultCenter ] ;
2004-12-15 06:51:55 +00:00
2002-08-14 00:01:42 +00:00
NSDebugLog ( @ "setSelectionFromEditor %@" , anEditor ) ;
2005-03-08 05:11:41 +00:00
ASSIGN ( lastEditor , anEditor ) ;
2005-03-31 03:01:36 +00:00
[ ( id < Gorm > ) NSApp stopConnecting ] ; // cease any connection
2003-05-10 21:19:25 +00:00
if ( [ ( NSObject * ) anEditor respondsToSelector : @ selector ( window ) ] )
2002-08-20 04:46:07 +00:00
{
2005-03-08 03:12:32 +00:00
[ [ anEditor window ] makeKeyWindow ] ;
2004-04-03 18:21:54 +00:00
[ [ anEditor window ] makeFirstResponder : ( id ) anEditor ] ;
2002-08-20 04:46:07 +00:00
}
1999-12-14 17:38:17 +00:00
[ nc postNotificationName : IBSelectionChangedNotification
object : anEditor ] ;
1999-12-08 15:19:11 +00:00
}
2005-07-05 14:58:42 +00:00
/ * *
* Mark the document as modified .
* /
1999-12-08 15:04:57 +00:00
- ( void ) touch
{
1999-12-14 19:55:18 +00:00
[ window setDocumentEdited : YES ] ;
}
2005-07-05 14:58:42 +00:00
/ * *
* Returns the window and the rect r for object .
* /
1999-12-18 08:55:31 +00:00
- ( NSWindow * ) windowAndRect : ( NSRect * ) r forObject : ( id ) object
{
2000-01-13 21:19:03 +00:00
/ *
* Get the window and rectangle for which link markup should be drawn .
* /
1999-12-18 08:55:31 +00:00
if ( [ objectsView containsObject : object ] = = YES )
{
2000-01-13 21:19:03 +00:00
/ *
* objects that exist in the document objects view must have their link
* markup drawn there , so we ask the view for the required rectangle .
* /
* r = [ objectsView rectForObject : object ] ;
1999-12-18 08:55:31 +00:00
return [ objectsView window ] ;
}
2000-01-13 21:19:03 +00:00
else if ( [ object isKindOfClass : [ NSMenuItem class ] ] = = YES )
1999-12-18 08:55:31 +00:00
{
2000-01-13 21:19:03 +00:00
NSArray * links ;
NSMenu * menu ;
id editor ;
1999-12-18 08:55:31 +00:00
2000-01-13 21:19:03 +00:00
/ *
* Menu items must have their markup drawn in the window of the
* editor of the parent menu .
* /
links = [ self connectorsForSource : object
ofClass : [ NSNibConnector class ] ] ;
menu = [ [ links lastObject ] destination ] ;
editor = [ self editorForObject : menu create : NO ] ;
* r = [ editor rectForObject : object ] ;
return [ editor window ] ;
}
else if ( [ object isKindOfClass : [ NSView class ] ] = = YES )
{
/ *
2002-08-14 00:01:42 +00:00
* Normal view objects just get link markup drawn on them .
2000-01-13 21:19:03 +00:00
* /
2002-08-14 00:01:42 +00:00
id temp = object ;
id editor = [ self editorForObject : temp create : NO ] ;
2003-02-13 13:32:59 +00:00
while ( ( temp ! = nil ) && ( editor = = nil ) )
2002-08-14 00:01:42 +00:00
{
temp = [ temp superview ] ;
editor = [ self editorForObject : temp create : NO ] ;
}
if ( temp = = nil )
{
* r = [ object convertRect : [ object bounds ] toView : nil ] ;
}
else if ( [ editor respondsToSelector :
@ selector ( windowAndRect : forObject : ) ] )
{
return [ editor windowAndRect : r forObject : object ] ;
}
1999-12-18 08:55:31 +00:00
}
2002-03-29 16:30:01 +00:00
else if ( [ object isKindOfClass : [ NSTableColumn class ] ] = = YES )
{
NSTableView * tv = [ [ ( NSTableColumn * ) object dataCell ] controlView ] ;
NSTableHeaderView * th = [ tv headerView ] ;
int index ;
if ( th = = nil || tv = = nil )
{
2004-02-21 18:48:48 +00:00
NSDebugLog ( @ "fail 1 %@ %@ %@" , [ ( NSTableColumn * ) object headerCell ] , th , tv ) ;
2002-03-29 16:30:01 +00:00
* r = NSZeroRect ;
return nil ;
}
index = [ [ tv tableColumns ] indexOfObject : object ] ;
if ( index = = NSNotFound )
{
2004-02-21 18:48:48 +00:00
NSDebugLog ( @ "fail 2" ) ;
2002-03-29 16:30:01 +00:00
* r = NSZeroRect ;
return nil ;
}
* r = [ th convertRect : [ th headerRectOfColumn : index ]
toView : nil ] ;
return [ th window ] ;
}
1999-12-18 08:55:31 +00:00
else
{
* r = NSZeroRect ;
return nil ;
}
2002-08-14 00:01:42 +00:00
// never reached , keeps gcc happy
return nil ;
1999-12-18 08:55:31 +00:00
}
2005-07-05 14:58:42 +00:00
/ * *
* The document window .
* /
2000-01-04 16:25:39 +00:00
- ( NSWindow * ) window
{
return window ;
}
2005-07-05 14:58:42 +00:00
/ * *
* Determine if the document should be closed or not .
* /
2003-05-20 03:57:37 +00:00
- ( BOOL ) couldCloseDocument
1999-12-14 19:55:18 +00:00
{
if ( [ window isDocumentEdited ] = = YES )
{
NSString * msg ;
int result ;
2000-01-04 17:46:26 +00:00
if ( documentPath = = nil )
1999-12-14 19:55:18 +00:00
{
2003-05-24 12:40:54 +00:00
msg = _ ( @ "Document 'UNTITLED' has been modified" ) ;
1999-12-14 19:55:18 +00:00
}
else
{
2003-05-24 12:40:54 +00:00
msg = [ NSString stringWithFormat : _ ( @ "Document '%@' has been modified" ) ,
1999-12-14 19:55:18 +00:00
[ documentPath lastPathComponent ] ] ;
}
2005-02-05 14:11:57 +00:00
result = NSRunAlertPanel ( _ ( @ "Close Document" ) ,
msg ,
_ ( @ "Save" ) ,
_ ( @ "Don't Save" ) ,
_ ( @ "Cancel" ) ) ;
2003-05-20 03:57:37 +00:00
if ( result = = NSAlertDefaultReturn )
{
// Save
if ( ! [ self saveGormDocument : self ] )
2004-08-08 17:23:17 +00:00
{
return NO ;
}
else
{
isDocumentOpen = NO ;
}
1999-12-14 19:55:18 +00:00
}
2003-05-20 03:57:37 +00:00
else if ( result = = NSAlertOtherReturn )
2004-08-08 17:23:17 +00:00
{
// Cancel
return NO ;
}
else // Don ' t save . . .
{
isDocumentOpen = NO ;
}
2004-05-13 05:13:36 +00:00
}
2003-05-20 03:57:37 +00:00
2004-05-13 05:13:36 +00:00
return YES ;
2003-05-20 03:57:37 +00:00
}
2004-05-13 05:13:36 +00:00
2005-07-05 14:58:42 +00:00
/ * *
* Called when the document window close is selected .
* /
2003-05-20 03:57:37 +00:00
- ( BOOL ) windowShouldClose : ( id ) sender
{
return [ self couldCloseDocument ] ;
1999-12-08 15:04:57 +00:00
}
2005-07-05 14:58:42 +00:00
/ * *
* Removes all connections given action or outlet with the specified label
* ( paramter name ) class name ( parameter className ) .
* /
2002-11-23 23:33:17 +00:00
- ( BOOL ) removeConnectionsWithLabel : ( NSString * ) name
2002-11-23 04:45:04 +00:00
forClassNamed : ( NSString * ) className
isAction : ( BOOL ) action
{
NSEnumerator * en = [ connections objectEnumerator ] ;
2005-01-31 06:32:16 +00:00
NSMutableArray * removedConnections = [ NSMutableArray array ] ;
2002-11-23 04:45:04 +00:00
id < IBConnectors > c = nil ;
2002-11-23 23:33:17 +00:00
BOOL removed = YES ;
2005-01-31 06:32:16 +00:00
BOOL prompted = NO ;
2002-11-23 04:45:04 +00:00
2005-01-31 06:32:16 +00:00
// find connectors to be removed .
2003-02-13 13:32:59 +00:00
while ( ( c = [ en nextObject ] ) ! = nil )
2002-11-23 04:45:04 +00:00
{
id proxy = nil ;
2005-01-31 06:32:16 +00:00
NSString * proxyClass = nil ;
2002-11-23 04:45:04 +00:00
NSString * label = [ c label ] ;
2005-01-31 06:32:16 +00:00
if ( label = = nil )
continue ;
2003-02-13 13:32:59 +00:00
if ( action )
2002-11-23 04:45:04 +00:00
{
2003-02-13 13:32:59 +00:00
if ( ! [ label hasSuffix : @ ":" ] )
2002-11-23 04:45:04 +00:00
continue ;
2005-01-31 06:32:16 +00:00
if ( ! [ classManager isAction : label ofClass : className ] )
continue ;
2002-11-23 04:45:04 +00:00
proxy = [ c destination ] ;
}
else
{
2003-02-13 13:32:59 +00:00
if ( [ label hasSuffix : @ ":" ] )
2002-11-23 04:45:04 +00:00
continue ;
2005-01-31 06:32:16 +00:00
if ( ! [ classManager isOutlet : label ofClass : className ] )
continue ;
2002-11-23 04:45:04 +00:00
proxy = [ c source ] ;
}
2005-01-31 06:32:16 +00:00
// get the class for the current connectors object
proxyClass = [ proxy className ] ;
if ( [ label isEqualToString : name ] && ( [ proxyClass isEqualToString : className ] ||
[ classManager isSuperclass : className linkedToClass : proxyClass ] ) )
2002-11-23 04:45:04 +00:00
{
2003-02-13 13:32:59 +00:00
NSString * title ;
NSString * msg ;
int retval ;
2005-01-31 06:32:16 +00:00
if ( prompted = = NO )
{
title = [ NSString stringWithFormat :
@ "Modifying %@" , ( action = = YES ? @ "Action" : @ "Outlet" ) ] ;
msg = [ NSString stringWithFormat :
_ ( @ "This will break all connections to '%@'. Continue?" ) , name ] ;
retval = NSRunAlertPanel ( title , msg , _ ( @ "OK" ) , _ ( @ "Cancel" ) , nil , nil ) ;
prompted = YES ;
}
2003-02-13 13:32:59 +00:00
if ( retval = = NSAlertDefaultReturn )
2002-11-23 23:33:17 +00:00
{
removed = YES ;
2005-01-31 06:32:16 +00:00
[ removedConnections addObject : c ] ;
2002-11-23 23:33:17 +00:00
}
else
{
removed = NO ;
2005-02-03 03:41:18 +00:00
break ;
2002-11-23 23:33:17 +00:00
}
2002-11-23 04:45:04 +00:00
}
}
2005-01-31 06:32:16 +00:00
// actually remove the connections .
if ( removed )
{
en = [ removedConnections objectEnumerator ] ;
while ( ( c = [ en nextObject ] ) ! = nil )
{
[ self removeConnector : c ] ;
}
}
2002-11-23 04:45:04 +00:00
// done . . .
2003-02-13 13:32:59 +00:00
NSDebugLog ( @ "Removed references to %@ on %@" , name , className ) ;
2002-11-23 23:33:17 +00:00
return removed ;
2002-11-23 04:45:04 +00:00
}
2005-07-05 14:58:42 +00:00
/ * *
* Remove all connections to any and all instances of className .
* /
2002-11-30 00:49:55 +00:00
- ( BOOL ) removeConnectionsForClassNamed : ( NSString * ) className
{
2005-01-31 06:32:16 +00:00
NSEnumerator * en = nil ;
2002-11-30 00:49:55 +00:00
id < IBConnectors > c = nil ;
BOOL removed = YES ;
int retval = -1 ;
2003-05-24 12:40:54 +00:00
NSString * title = [ NSString stringWithFormat : _ ( @ "Modifying Class" ) ] ;
2003-02-13 13:32:59 +00:00
NSString * msg ;
2003-05-24 12:40:54 +00:00
msg = [ NSString stringWithFormat : _ ( @ "This will break all connections to "
2005-01-31 06:32:16 +00:00
@ "actions/outlets to instances of class '%@' and it's subclasses. Continue?" ) , className ] ;
2002-11-30 00:49:55 +00:00
// ask the user if he / she wants to continue . . .
2003-05-24 12:40:54 +00:00
retval = NSRunAlertPanel ( title , msg , _ ( @ "OK" ) , _ ( @ "Cancel" ) , nil , nil ) ;
2003-02-13 13:32:59 +00:00
if ( retval = = NSAlertDefaultReturn )
2002-11-30 00:49:55 +00:00
{
removed = YES ;
}
else
{
removed = NO ;
}
// remove all .
2004-12-16 10:38:14 +00:00
if ( removed )
2002-11-30 00:49:55 +00:00
{
2005-01-31 06:32:16 +00:00
NSMutableArray * removedConnections = [ NSMutableArray array ] ;
// first find all of the connections . . .
en = [ connections objectEnumerator ] ;
2004-12-16 10:38:14 +00:00
while ( ( c = [ en nextObject ] ) ! = nil )
2002-11-30 00:49:55 +00:00
{
2005-01-31 06:32:16 +00:00
NSString * srcClass = [ [ c source ] className ] ;
NSString * dstClass = [ [ c destination ] className ] ;
if ( [ srcClass isEqualToString : className ] ||
[ classManager isSuperclass : className linkedToClass : srcClass ] ||
[ dstClass isEqualToString : className ] ||
[ classManager isSuperclass : className linkedToClass : dstClass ] )
2004-12-16 10:38:14 +00:00
{
2005-01-31 06:32:16 +00:00
[ removedConnections addObject : c ] ;
2004-12-16 10:38:14 +00:00
}
2002-11-30 00:49:55 +00:00
}
2005-01-31 06:32:16 +00:00
// then remove them .
en = [ removedConnections objectEnumerator ] ;
while ( ( c = [ en nextObject ] ) ! = nil )
{
[ self removeConnector : c ] ;
}
2002-11-30 00:49:55 +00:00
}
// done . . .
2003-02-13 13:32:59 +00:00
NSDebugLog ( @ "Removed references to actions/outlets for objects of %@" ,
className ) ;
2002-11-30 00:49:55 +00:00
return removed ;
}
2005-07-05 14:58:42 +00:00
/ * *
* Rename connections connected to an instance of on class to another .
* /
2002-12-05 05:23:08 +00:00
- ( BOOL ) renameConnectionsForClassNamed : ( NSString * ) className
toName : ( NSString * ) newName
{
NSEnumerator * en = [ connections objectEnumerator ] ;
id < IBConnectors > c = nil ;
2005-04-11 20:42:33 +00:00
BOOL renamed = YES ;
2002-12-05 05:23:08 +00:00
int retval = -1 ;
2003-05-24 12:40:54 +00:00
NSString * title = [ NSString stringWithFormat : _ ( @ "Modifying Class" ) ] ;
2002-12-05 05:23:08 +00:00
NSString * msg = [ NSString stringWithFormat :
2003-05-24 12:40:54 +00:00
_ ( @ "Change class name '%@' to '%@'. Continue?" ) ,
2002-12-05 05:23:08 +00:00
className , newName ] ;
// ask the user if he / she wants to continue . . .
2003-05-24 12:40:54 +00:00
retval = NSRunAlertPanel ( title , msg , _ ( @ "OK" ) , _ ( @ "Cancel" ) , nil , nil ) ;
2003-02-13 13:32:59 +00:00
if ( retval = = NSAlertDefaultReturn )
2002-12-05 05:23:08 +00:00
{
2005-04-11 20:42:33 +00:00
renamed = YES ;
2002-12-05 05:23:08 +00:00
}
else
{
2005-04-11 20:42:33 +00:00
renamed = NO ;
2002-12-05 05:23:08 +00:00
}
// remove all .
2005-04-11 20:42:33 +00:00
if ( renamed )
2002-12-05 05:23:08 +00:00
{
2004-12-16 10:38:14 +00:00
while ( ( c = [ en nextObject ] ) ! = nil )
2002-12-05 05:23:08 +00:00
{
2004-12-16 10:38:14 +00:00
id source = [ c source ] ;
id destination = [ c destination ] ;
// check both . . .
if ( [ [ [ c source ] className ] isEqualToString : className ] )
{
[ source setClassName : newName ] ;
NSDebugLog ( @ "Found matching source" ) ;
}
else if ( [ [ [ c destination ] className ] isEqualToString : className ] )
{
[ destination setClassName : newName ] ;
NSDebugLog ( @ "Found matching destination" ) ;
}
2002-12-05 05:23:08 +00:00
}
}
// done . . .
NSDebugLog ( @ "Changed references to actions/outlets for objects of %@" , className ) ;
2005-04-11 20:42:33 +00:00
return renamed ;
2002-12-05 05:23:08 +00:00
}
2003-06-06 06:24:46 +00:00
2005-07-05 14:58:42 +00:00
/ * *
* Print out all editors for debugging purposes .
* /
2002-08-14 00:01:42 +00:00
- ( void ) printAllEditors
{
NSMutableSet * set = [ NSMutableSet setWithCapacity : 16 ] ;
NSEnumerator * enumerator = [ connections objectEnumerator ] ;
id < IBConnectors > c ;
while ( ( c = [ enumerator nextObject ] ) ! = nil )
{
if ( [ GormObjectToEditor class ] = = [ c class ] )
{
[ set addObject : [ c destination ] ] ;
}
}
NSLog ( @ "all editors %@" , set ) ;
}
2002-11-04 13:52:31 +00:00
2005-07-05 14:58:42 +00:00
/ * *
* Open a sound and load it into the document .
* /
2002-11-04 13:52:31 +00:00
- ( id ) openSound : ( id ) sender
{
NSArray * fileTypes = [ NSSound soundUnfilteredFileTypes ] ;
2003-06-29 17:23:39 +00:00
NSArray * filenames ;
NSString * filename ;
2002-11-04 13:52:31 +00:00
NSOpenPanel * oPanel = [ NSOpenPanel openPanel ] ;
int result ;
2003-06-29 17:23:39 +00:00
int i ;
2002-11-04 13:52:31 +00:00
2003-06-29 17:23:39 +00:00
[ oPanel setAllowsMultipleSelection : YES ] ;
2002-11-04 13:52:31 +00:00
[ oPanel setCanChooseFiles : YES ] ;
[ oPanel setCanChooseDirectories : NO ] ;
result = [ oPanel runModalForDirectory : nil
file : nil
types : fileTypes ] ;
if ( result = = NSOKButton )
{
2003-06-29 17:23:39 +00:00
filenames = [ oPanel filenames ] ;
for ( i = 0 ; i < [ filenames count ] ; i + + )
{
filename = [ filenames objectAtIndex : i ] ;
NSDebugLog ( @ "Loading sound file: %@" , filenames ) ;
2004-12-05 20:52:36 +00:00
[ soundsView addObject : [ GormSound soundForPath : filename ] ] ;
2003-06-29 17:23:39 +00:00
}
2002-11-04 13:52:31 +00:00
return self ;
}
return nil ;
}
2002-11-05 05:42:45 +00:00
2005-07-05 14:58:42 +00:00
/ * *
* Open an image and copy it into the document .
* /
2002-11-18 20:54:26 +00:00
- ( id ) openImage : ( id ) sender
{
NSArray * fileTypes = [ NSImage imageFileTypes ] ;
2003-06-29 17:23:39 +00:00
NSArray * filenames ;
2002-11-18 20:54:26 +00:00
NSOpenPanel * oPanel = [ NSOpenPanel openPanel ] ;
2003-06-29 17:23:39 +00:00
NSString * filename ;
2002-11-18 20:54:26 +00:00
int result ;
2003-06-29 17:23:39 +00:00
int i ;
2002-11-18 20:54:26 +00:00
2003-06-29 17:23:39 +00:00
[ oPanel setAllowsMultipleSelection : YES ] ;
2002-11-18 20:54:26 +00:00
[ oPanel setCanChooseFiles : YES ] ;
[ oPanel setCanChooseDirectories : NO ] ;
result = [ oPanel runModalForDirectory : nil
file : nil
types : fileTypes ] ;
if ( result = = NSOKButton )
{
2003-06-29 17:23:39 +00:00
filenames = [ oPanel filenames ] ;
for ( i = 0 ; i < [ filenames count ] ; i + + )
{
filename = [ filenames objectAtIndex : i ] ;
NSDebugLog ( @ "Loading image file: %@" , filename ) ;
2004-12-05 20:52:36 +00:00
[ imagesView addObject : [ GormImage imageForPath : filename ] ] ;
2003-06-29 17:23:39 +00:00
}
2002-11-18 20:54:26 +00:00
return self ;
}
return nil ;
}
2005-07-05 14:58:42 +00:00
/ * *
* Return a text description of the document .
* /
2003-10-18 06:20:45 +00:00
- ( NSString * ) description
{
return [ NSString stringWithFormat : @ "<%s: %lx> = %@" ,
GSClassNameFromObject ( self ) ,
( unsigned long ) self ,
nameTable ] ;
}
2003-12-24 02:50:34 +00:00
2005-07-05 14:58:42 +00:00
/ * *
* Returns YES , if obj is a top level object .
* /
2004-08-12 02:33:17 +00:00
- ( BOOL ) isTopLevelObject : ( id ) obj
{
2004-08-13 01:37:18 +00:00
return [ topLevelObjects containsObject : obj ] ;
2004-08-12 02:33:17 +00:00
}
2005-07-05 14:58:42 +00:00
/ * *
* Return first responder stand in .
* /
2004-03-21 15:33:28 +00:00
- ( id ) firstResponder
{
return firstResponder ;
}
2005-07-05 14:58:42 +00:00
/ * *
* Return font manager standin .
* /
2004-03-21 15:33:28 +00:00
- ( id ) fontManager
{
return fontManager ;
}
2005-04-10 22:21:59 +00:00
2005-07-05 14:58:42 +00:00
/ * *
* Create resource manager instances for all registered classes .
* /
2005-04-10 22:21:59 +00:00
- ( void ) createResourceManagers
{
NSArray * resourceClasses = [ IBResourceManager registeredResourceManagerClassesForFramework : nil ] ;
NSEnumerator * en = [ resourceClasses objectEnumerator ] ;
Class cls = nil ;
if ( resourceManagers ! = nil )
{
// refresh . . .
DESTROY ( resourceManagers ) ;
}
resourceManagers = [ [ NSMutableArray alloc ] init ] ;
while ( ( cls = [ en nextObject ] ) ! = nil )
{
2005-04-11 20:42:33 +00:00
id mgr = AUTORELEASE ( [ ( IBResourceManager * ) [ cls alloc ] initWithDocument : self ] ) ;
2005-04-10 22:21:59 +00:00
[ resourceManagers addObject : mgr ] ;
}
}
2005-07-05 14:58:42 +00:00
/ * *
* The list of all resource managers .
* /
2005-04-10 22:21:59 +00:00
- ( NSArray * ) resourceManagers
{
return resourceManagers ;
}
2005-04-11 00:16:01 +00:00
2005-07-05 14:58:42 +00:00
/ * *
* Get the resource manager which handles the content on pboard .
* /
2005-04-11 00:16:01 +00:00
- ( IBResourceManager * ) resourceManagerForPasteboard : ( NSPasteboard * ) pboard
{
NSEnumerator * en = [ resourceManagers objectEnumerator ] ;
IBResourceManager * mgr = nil , * result = nil ;
while ( ( mgr = [ en nextObject ] ) ! = nil )
{
if ( [ mgr acceptsResourcesFromPasteboard : pboard ] )
{
result = mgr ;
break ;
}
}
return result ;
}
2005-04-24 00:15:57 +00:00
2005-07-05 14:58:42 +00:00
/ * *
* Get all pasteboard types managed by the resource manager .
* /
2005-04-24 00:15:57 +00:00
- ( NSArray * ) allManagedPboardTypes
{
NSMutableArray * allTypes = [ [ NSMutableArray alloc ] initWithObjects : NSFilenamesPboardType ,
GormLinkPboardType ,
nil ] ;
NSArray * mgrs = [ self resourceManagers ] ;
NSEnumerator * en = [ mgrs objectEnumerator ] ;
IBResourceManager * mgr = nil ;
AUTORELEASE ( allTypes ) ;
while ( ( mgr = [ en nextObject ] ) ! = nil )
{
NSArray * pbTypes = [ mgr resourcePasteboardTypes ] ;
[ allTypes addObjectsFromArray : pbTypes ] ;
}
return allTypes ;
}
2005-06-10 11:43:51 +00:00
2005-06-11 18:06:43 +00:00
// language translation methods .
/ * *
2005-06-13 03:14:57 +00:00
* This method collects all of the objects in the document .
2005-06-11 18:06:43 +00:00
* /
2005-06-13 03:14:57 +00:00
- ( NSArray * ) _collectAllObjects
2005-06-11 18:06:43 +00:00
{
NSMutableArray * allObjects = [ NSMutableArray arrayWithArray : [ topLevelObjects allObjects ] ] ;
NSEnumerator * en = [ topLevelObjects objectEnumerator ] ;
NSMutableArray * removeObjects = [ NSMutableArray array ] ;
id obj = nil ;
// collect all subviews / menus / etc .
while ( ( obj = [ en nextObject ] ) ! = nil )
{
if ( [ obj isKindOfClass : [ NSWindow class ] ] )
{
NSMutableArray * views = [ NSMutableArray array ] ;
NSEnumerator * ven = [ views objectEnumerator ] ;
id vobj = nil ;
subviewsForView ( [ ( NSWindow * ) obj contentView ] , views ) ;
[ allObjects addObjectsFromArray : views ] ;
while ( ( vobj = [ ven nextObject ] ) )
{
if ( [ vobj isKindOfClass : [ GormCustomView class ] ] )
{
[ removeObjects addObject : vobj ] ;
}
else if ( [ vobj isKindOfClass : [ NSMatrix class ] ] )
{
[ allObjects addObjectsFromArray : [ vobj cells ] ] ;
}
else if ( [ vobj isKindOfClass : [ NSPopUpButton class ] ] )
{
[ allObjects addObjectsFromArray : [ vobj itemArray ] ] ;
}
else if ( [ vobj isKindOfClass : [ NSTabView class ] ] )
{
[ allObjects addObjectsFromArray : [ vobj tabViewItems ] ] ;
}
}
}
else if ( [ obj isKindOfClass : [ NSMenu class ] ] )
{
[ allObjects addObjectsFromArray : findAll ( obj ) ] ;
}
}
// take out objects which shouldn ' t be considered .
[ allObjects removeObjectsInArray : removeObjects ] ;
return allObjects ;
}
2005-06-13 03:14:57 +00:00
/ * *
* This method is used to translate all of the strings in the file from one language
* into another . This is helpful when attempting to translate an application for use
* in different locales .
* /
2005-06-10 11:43:51 +00:00
- ( void ) translate
{
NSArray * fileTypes = [ NSArray arrayWithObjects : @ "strings" , nil ] ;
NSOpenPanel * oPanel = [ NSOpenPanel openPanel ] ;
int result ;
[ oPanel setAllowsMultipleSelection : NO ] ;
[ oPanel setCanChooseFiles : YES ] ;
[ oPanel setCanChooseDirectories : NO ] ;
result = [ oPanel runModalForDirectory : nil
file : nil
types : fileTypes ] ;
if ( result = = NSOKButton )
{
2005-06-13 03:14:57 +00:00
NSMutableArray * allObjects = [ self _collectAllObjects ] ;
2005-06-10 11:43:51 +00:00
NSString * filename = [ oPanel filename ] ;
NSDictionary * dictionary = [ [ NSString stringWithContentsOfFile : filename ] propertyListFromStringsFileFormat ] ;
2005-06-11 18:06:43 +00:00
NSEnumerator * en = [ allObjects objectEnumerator ] ;
2005-06-10 11:43:51 +00:00
id obj = nil ;
2005-06-11 09:08:47 +00:00
// change to translated values .
while ( ( obj = [ en nextObject ] ) ! = nil )
{
2005-06-11 18:06:43 +00:00
NSString * translation = nil ;
2005-06-11 09:08:47 +00:00
2005-06-10 11:43:51 +00:00
if ( [ obj respondsToSelector : @ selector ( setTitle : ) ] &&
[ obj respondsToSelector : @ selector ( title ) ] )
{
2005-06-11 18:06:43 +00:00
translation = [ dictionary objectForKey : [ obj title ] ] ;
2005-06-10 11:43:51 +00:00
if ( translation ! = nil )
{
[ obj setTitle : translation ] ;
}
}
else if ( [ obj respondsToSelector : @ selector ( setStringValue : ) ] &&
[ obj respondsToSelector : @ selector ( stringValue ) ] )
{
2005-06-11 18:06:43 +00:00
translation = [ dictionary objectForKey : [ obj stringValue ] ] ;
2005-06-10 11:43:51 +00:00
if ( translation ! = nil )
{
[ obj setStringValue : translation ] ;
2005-06-11 09:08:47 +00:00
}
}
else if ( [ obj respondsToSelector : @ selector ( setLabel : ) ] &&
[ obj respondsToSelector : @ selector ( label ) ] )
{
2005-06-11 18:06:43 +00:00
translation = [ dictionary objectForKey : [ obj label ] ] ;
2005-06-11 09:08:47 +00:00
if ( translation ! = nil )
{
[ obj setLabel : translation ] ;
}
}
2005-06-11 18:06:43 +00:00
if ( translation ! = nil )
2005-06-11 09:08:47 +00:00
{
if ( [ obj isKindOfClass : [ NSView class ] ] )
{
[ obj setNeedsDisplay : YES ] ;
2005-06-10 11:43:51 +00:00
}
2005-06-11 18:06:43 +00:00
[ self touch ] ;
}
2005-06-15 00:34:36 +00:00
// redisplay / flush , if the object is a window .
if ( [ obj isKindOfClass : [ NSWindow class ] ] )
{
NSWindow * w = ( NSWindow * ) obj ;
[ w setViewsNeedDisplay : YES ] ;
[ w disableFlushWindow ] ;
[ [ w contentView ] setNeedsDisplay : YES ] ;
[ [ w contentView ] displayIfNeeded ] ;
[ w enableFlushWindow ] ;
[ w flushWindowIfNeeded ] ;
}
2005-06-11 18:06:43 +00:00
}
}
}
/ * *
* This method is used to export all strings in a document to a file for Language
* translation . This allows the user to see all of the strings which can be translated
* and allows the user to provide a translateion for each of them .
* /
- ( void ) exportStrings
{
NSOpenPanel * sp = [ NSSavePanel savePanel ] ;
int result ;
[ sp setRequiredFileType : @ "strings" ] ;
[ sp setTitle : _ ( @ "Save strings file as..." ) ] ;
result = [ sp runModalForDirectory : NSHomeDirectory ( )
file : nil ] ;
if ( result = = NSOKButton )
{
2005-06-13 03:14:57 +00:00
NSMutableArray * allObjects = [ self _collectAllObjects ] ;
2005-06-11 18:06:43 +00:00
NSString * filename = [ sp filename ] ;
NSMutableDictionary * dictionary = [ NSMutableDictionary dictionary ] ;
NSEnumerator * en = [ allObjects objectEnumerator ] ;
id obj = nil ;
BOOL touched = NO ;
// change to translated values .
while ( ( obj = [ en nextObject ] ) ! = nil )
{
NSString * string = nil ;
if ( [ obj respondsToSelector : @ selector ( setTitle : ) ] &&
[ obj respondsToSelector : @ selector ( title ) ] )
{
string = [ obj title ] ;
}
else if ( [ obj respondsToSelector : @ selector ( setStringValue : ) ] &&
[ obj respondsToSelector : @ selector ( stringValue ) ] )
{
string = [ obj stringValue ] ;
}
else if ( [ obj respondsToSelector : @ selector ( setLabel : ) ] &&
[ obj respondsToSelector : @ selector ( label ) ] )
{
string = [ obj label ] ;
}
if ( string ! = nil )
{
[ dictionary setObject : string forKey : string ] ;
touched = YES ;
2005-06-10 11:43:51 +00:00
}
}
if ( touched )
{
2005-06-11 18:06:43 +00:00
NSString * stringToWrite = [ dictionary descriptionInStringsFileFormat ] ;
[ stringToWrite writeToFile : filename atomically : YES ] ;
2005-06-10 11:43:51 +00:00
}
}
}
2005-07-04 21:53:33 +00:00
2005-07-05 14:58:42 +00:00
/ * *
* Arrange views in front or in back of one another .
* /
2005-07-04 21:53:33 +00:00
- ( void ) arrangeSelectedObjects : ( id ) sender
{
NSArray * selection = [ [ ( id < IB > ) NSApp selectionOwner ] selection ] ;
int tag = [ sender tag ] ;
NSEnumerator * en = [ selection objectEnumerator ] ;
id v = nil ;
while ( ( v = [ en nextObject ] ) ! = nil )
{
if ( [ v isKindOfClass : [ NSView class ] ] )
{
id editor = [ self editorForObject : v create : NO ] ;
if ( [ editor respondsToSelector : @ selector ( superview ) ] )
{
id superview = [ editor superview ] ;
if ( tag = = 0 ) // bring to front . . .
{
[ superview moveViewToFront : editor ] ;
}
else if ( tag = = 1 ) // send to back
{
[ superview moveViewToBack : editor ] ;
}
[ superview setNeedsDisplay : YES ] ;
}
}
}
}
2005-07-05 14:58:42 +00:00
/ * *
* Align objects to center , left , right , top , bottom .
* /
2005-07-04 21:53:33 +00:00
- ( void ) alignSelectedObjects : ( id ) sender
{
NSArray * selection = [ [ ( id < IB > ) NSApp selectionOwner ] selection ] ;
int tag = [ sender tag ] ;
NSEnumerator * en = [ selection objectEnumerator ] ;
id v = nil ;
id prev = nil ;
while ( ( v = [ en nextObject ] ) ! = nil )
{
if ( [ v isKindOfClass : [ NSView class ] ] )
{
id editor = [ self editorForObject : v create : NO ] ;
if ( prev ! = nil )
{
NSRect r = [ prev frame ] ;
NSRect e = [ editor frame ] ;
if ( tag = = 0 ) // center vertically
{
float center = ( r . origin . x + ( r . size . width / 2 ) ) ;
e . origin . x = ( center - ( e . size . width / 2 ) ) ;
}
else if ( tag = = 1 ) // center horizontally
{
float center = ( r . origin . y + ( r . size . height / 2 ) ) ;
e . origin . y = ( center - ( e . size . height / 2 ) ) ;
}
else if ( tag = = 2 ) // align left
{
e . origin . x = r . origin . x ;
}
else if ( tag = = 3 ) // align right
{
float right = ( r . origin . x + r . size . width ) ;
e . origin . x = ( right - e . size . width ) ;
}
else if ( tag = = 4 ) // align top
{
float top = ( r . origin . y + r . size . height ) ;
e . origin . y = ( top - e . size . height ) ;
}
else if ( tag = = 5 ) // align bottom
{
e . origin . y = r . origin . y ;
}
[ editor setFrame : e ] ;
[ [ editor superview ] setNeedsDisplay : YES ] ;
}
prev = editor ;
}
}
}
1999-12-08 15:04:57 +00:00
@ end
2003-01-01 17:50:17 +00:00
@ implementation GormDocument ( MenuValidation )
- ( BOOL ) isEditingObjects
{
return ( [ selectionBox contentView ] = = scrollView ) ;
}
- ( BOOL ) isEditingImages
{
return ( [ selectionBox contentView ] = = imagesScrollView ) ;
}
- ( BOOL ) isEditingSounds
{
return ( [ selectionBox contentView ] = = soundsScrollView ) ;
}
- ( BOOL ) isEditingClasses
{
2005-05-04 09:34:49 +00:00
return ( [ selectionBox contentView ] = = classesView ) ;
2003-01-01 17:50:17 +00:00
}
@ end
2004-05-20 02:34:03 +00:00
@ implementation GormDocument ( NSToolbarDelegate )
- ( NSToolbarItem * ) toolbar : ( NSToolbar * ) toolbar
itemForItemIdentifier : ( NSString * ) itemIdentifier
willBeInsertedIntoToolbar : ( BOOL ) flag
{
NSToolbarItem * toolbarItem = AUTORELEASE ( [ [ NSToolbarItem alloc ]
initWithItemIdentifier : itemIdentifier ] ) ;
if ( [ itemIdentifier isEqual : @ "ObjectsItem" ] )
{
[ toolbarItem setLabel : @ "Objects" ] ;
[ toolbarItem setImage : objectsImage ] ;
[ toolbarItem setTarget : self ] ;
[ toolbarItem setAction : @ selector ( changeView : ) ] ;
[ toolbarItem setTag : 0 ] ;
}
else if ( [ itemIdentifier isEqual : @ "ImagesItem" ] )
{
[ toolbarItem setLabel : @ "Images" ] ;
[ toolbarItem setImage : imagesImage ] ;
[ toolbarItem setTarget : self ] ;
[ toolbarItem setAction : @ selector ( changeView : ) ] ;
[ toolbarItem setTag : 1 ] ;
}
else if ( [ itemIdentifier isEqual : @ "SoundsItem" ] )
{
[ toolbarItem setLabel : @ "Sounds" ] ;
[ toolbarItem setImage : soundsImage ] ;
[ toolbarItem setTarget : self ] ;
[ toolbarItem setAction : @ selector ( changeView : ) ] ;
[ toolbarItem setTag : 2 ] ;
}
else if ( [ itemIdentifier isEqual : @ "ClassesItem" ] )
{
[ toolbarItem setLabel : @ "Classes" ] ;
[ toolbarItem setImage : classesImage ] ;
[ toolbarItem setTarget : self ] ;
[ toolbarItem setAction : @ selector ( changeView : ) ] ;
[ toolbarItem setTag : 3 ] ;
}
2004-07-12 04:16:09 +00:00
else if ( [ itemIdentifier isEqual : @ "FileItem" ] )
{
[ toolbarItem setLabel : @ "File" ] ;
[ toolbarItem setImage : fileImage ] ;
[ toolbarItem setTarget : self ] ;
[ toolbarItem setAction : @ selector ( changeView : ) ] ;
[ toolbarItem setTag : 4 ] ;
}
2004-05-20 02:34:03 +00:00
return toolbarItem ;
}
- ( NSArray * ) toolbarAllowedItemIdentifiers : ( NSToolbar * ) toolbar
{
return [ NSArray arrayWithObjects : @ "ObjectsItem" ,
@ "ImagesItem" ,
@ "SoundsItem" ,
2004-07-12 04:16:09 +00:00
@ "ClassesItem" ,
@ "FileItem" ,
nil ] ;
2004-05-20 02:34:03 +00:00
}
- ( NSArray * ) toolbarDefaultItemIdentifiers : ( NSToolbar * ) toolbar
{
return [ NSArray arrayWithObjects : @ "ObjectsItem" ,
@ "ImagesItem" ,
@ "SoundsItem" ,
2004-07-12 04:16:09 +00:00
@ "ClassesItem" ,
@ "FileItem" ,
nil ] ;
2004-05-20 02:34:03 +00:00
}
@ end