#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
#include <Renaissance/Renaissance.h>
int main (int argc, const char **argv, char** env)
{
CREATE_AUTORELEASE_POOL (pool);
[NSApplication sharedApplication];
[NSApp setDelegate: [MyApplicationDelegate new]];
/* Load the menu before calling NSApplicationMain(), because on
* Apple Mac OS X NSApplicationMain() creates automatically a menu
* if none is there, and when we try to replace it later, it doesn't
* really get replaced ... (?)
*
* After extensive experiments, loading the menu at this stage is the best
* way of having it work on both platforms.
*/
#ifdef GNUSTEP
[NSBundle loadGSMarkupNamed: @"MainMenu-GNUstep" owner: [NSApp delegate]];
#else
[NSBundle loadGSMarkupNamed: @"MainMenu-OSX" owner: [NSApp delegate]];
#endif
RELEASE (pool);
return NSApplicationMain (argc, argv);
}
Please note that in the example we have two separate gsmarkup files
for the menu on the different platforms. While it can be clumsy to do
so, it's certainly the way which works best at the moment - unless
you know what you are doing, it's recommended that you do it this way
(and that you check/use default template examples of main menu
gsmarkup files). Finally, we set an instance of an hypothetic
MyApplicationDelegate as the application delegate.
That is only an example, but implementing an application delegate
custom class can be useful for loading the main window gsmarkup if you
need so, as explained in the next section.
In practice, you can implement your own application delegate class, and have it implement the
- (void)applicationDidFinishLaunching: (NSNotification *)aNotification;method. This method will be called when the application has finished launching; you can load the main window gsmarkup from there. For example:
@interface MyApplicationDelegate : NSObject
{
/* ... */
}
- (void)applicationDidFinishLaunching: (NSNotification *)aNotification;
@end
@implementation MyApplicationDelegate
- (void)applicationDidFinishLaunching: (NSNotification *)aNotification
{
[NSBundle loadGSMarkupNamed: @"MainWindow" owner: self];
}
@end
Of course, in your main function, you need to set an instance
of MyApplicationDelegate as the application delegate (as
demonstrated in the previous section). Please note that this is just
a very simple example: depending on how you are organizing the code in
your application, you might be loading the MainWindow from a
different object, or with a different owner - as a classical variant,
in -applicationDidFinishLaunching: you could be creating a
controller object, and that object might be loading the gsmarkup file
during initialization.
Renaissance includes full examples of applications demonstrating how to do all this - the first example you should look at is probably the CurrencyConverter example -
/Examples/Applications/CurrencyConverter
/* ... code here ... */ [NSBundle loadGSMarkupNamed: @"HighScores" owner: self]; /* ... more code here ... */that would load the HighScores.gsmarkup file from the main bundle, create the window(s) from the file, using self as the owner (assuming this method call is done inside a method implementation). The owner used when loading is quite important, because instance variables of the owner can be set to point to objects in the window (by using outlets in the gsmarkup file), and vice versa objects in the window can have some of their instance variables (/attributes) set to point to the file owner, so it is particularly natural to use as owner the object which will be interacting more closely and directly with the window while the program is running.
- (void) bundleDidLoadGSMarkup: (NSNotification *)aNotification;
NSDictionary *table;
NSMutableArray *topLevelObjects = [NSMutableArray array];
table = [NSDictionary dictionaryWithObjectsAndKeys:
self, @"NSOwner",
topLevelObjects, @"NSTopLevelObjects",
nil];
[NSBundle loadGSMarkupFile: @"MyFile"
externalNameTable: table
withZone: [self zone]];
/* Now topLevelObjects contains the top-level objects which
* were created from the gsmarkup file. */
This method of accessing the top-level objects is similar as the
method which can be used with NSBundleAdditions, where an undocumented
Apple extension can be used to get the top-level objects by adding a
key NSTopLevelObjects with value a mutable array to the
context dictionary.
- (void) bundleDidLoadGSMarkup: (NSNotification *)aNotification
{
NSArray *topLevelObjects;
topLevelObjects = [[aNotification userInfo] objectForKey:
@"NSTopLevelObjects"];
/* Now topLevelObjects contains the top-level objects which
* were created from the gsmarkup file. */
}
There is no equivalent of this method in the traditional NIB loading API.
GSMarkupBundleDidLoadGSMarkupThis is more advanced and more rarely useful; there is no equivalent of this method in the traditional NIB loading API.