Renaissance/GSMarkupBundleAdditions.hso you need to #include (or #import) that file to use them. This file is automatically included by
Renaissance/Renaissance.hso if you are including the general Renaissance.h header, the methods are automatically available. Please note that the API mirrors the existing NIB loading API which is traditionally found on OpenStep, with a few additional facilities.
int (*linkRenaissanceIn)(int, const char **) = GSMarkupApplicationMain;This defines a (dummy) function pointer called linkRenaissanceInt, and generates a reference to GSMarkupApplicationMain which fixes the problem.
+ (BOOL) loadGSMarkupFile: (NSString *)fileName externalNameTable: (NSDictionary *)context withZone: (NSZone *)zone localizableStringsTable: (NSString *)table inBundle: (NSBundle *)localizableStringsTableBundle;This method is the method which does the actual loading; other loading methods end up calling this one to do the loading. This method loads the file fileName (an absolute path) into the application. If fileName is missing the .gsmarkup extension, it is automatically appended. The file is read, and all the sections are parsed, resulting in a list of objects and of connectors, and a name table mapping id names to objects which have been decoded. The objects are then asked to replace themselves with the corresponding platform objects, and the name table is updated accordingly. While replacing themselves with the platform objects, the objects also translate the eventual text which might need to be translated by using the localizable strings given as argument, which is found in the bundle given as argument. Each type of objects knows which attributes or which content requires translation and which don't. Then, the context dictionary (which is supposed to contain a mapping of strings - id names - to objects already existing in the application; typically it contains at least the NSOwner object) is merged into the name table loaded from the file (except the special key-value pair with key NSTopLevelObjects, which is not added to the name table, and it is used later on for another task). The connections are finally established using the final name table. Last, all platform objects which were decoded from the file, and the NSOwner object, if it exists, are sent the awakeFromGSMarkup method. The top-level objects so created are not autoreleased - so unless they are released at some point, they will never be deallocated. This is correct for example for windows, which are normally released when the user closes them; it is also correct for some custom objects (the main controller object in the application), which are supposed to just exist for the whole lifetime of the application. But there are cases in which you might need access to the top-level objects, for example in order to release them. When Renaissance has loaded the file, it performs a few task which have the purpose of making the top-level objects available to the application. It posts the notification
GSMarkupBundleDidLoadGSMarkupNotificationwith the file owner as object, and a dictionary containing the key NSTopLevelObjects with value an array containing all the top-level objects as user info. If the file owner responds to the method
- (void) bundleDidLoadGSMarkup: (NSNotification *)notification;this method is automatically called with the notification as its argument, so you don't need to register the file owner to receive the notification. Finally, if the context dictionary contains a key NSTopLevelObjects, with value a NSMutableArray, this array is filled with the top-level objects created from the .gsmarkup file when it is read (for more information on retrieving the top-level objects, please refer to section 2.5.4). zone is supposed to be the memory zone from which all objects created when reading the file are allocated; but it is currently ignored, so you can pass NULL to it. The strings table and bundle arguments are used to translate the messages contained in the objects; if table is nil, the path extension is removed from the filename, and that is used as string table (so that localizable strings for the gsmarkup file example.gsmarkup are by default searched in the localizable strings file example.strings). If bundle is nil, the main bundle is used. The method returns YES if the file could be loaded, and NO otherwise.
+ (BOOL) loadGSMarkupFile: (NSString *)fileName externalNameTable: (NSDictionary *)context withZone: (NSZone *)zone;This method is a short form of the previous one; it simply calls it with nil table and nil bundle, which means that the localizable strings are translated using the strings table with the same name as the .gsmarkup file (extension removed) in the main bundle.
- (BOOL) loadGSMarkupFile: (NSString *)fileName externalNameTable: (NSDictionary *)context withZone: (NSZone *)zone localizableStringsTable: (NSString *)table;This method loads the gsmarkup file with name fileName (NB: if the fileName string does not have the extension .gsmarkup, it is automatically added) from the receiver bundle. The method first locates the file to load in the bundle, by searching as in the following example:
bundle_path/Resources/Italian.lproj/fileName.gsmarkup bundle_path/Resources/English.lproj/fileName.gsmarkup bundle_path/Resources/fileName.gsmarkup bundle_path/Italian.lproj/fileName.gsmarkup bundle_path/English.lproj/fileName.gsmarkup bundle_path/fileName.gsmarkupassuming that Italian.lproj is the user's preferred language. This algorithm differs from the standard bundle searching algorithm in that localized resources are preferred to non-localized ones (we're still all wondering why NSBundle does not have a standard method doing this by default). Once the file has been located and its absolute path on disk is known, the method finally calls the NSBundle method
+ loadGSMarkupFile: externalNameTable: withZone: localizableStringsTable: inBundle:with the given table as table argument, and the receiver bundle as bundle argument, to perform the actual loading.
- (BOOL) loadGSMarkupFile: (NSString *)fileName externalNameTable: (NSDictionary *)context withZone: (NSZone *)zone;This is a short form of the previous method, which uses a nil localizableStringsTable, which causes the localizable strings file with the same name as the gsmarkup file (extension removed) to be used as localizable strings table.
+ (BOOL) loadGSMarkupNamed: (NSString *)fileName owner: (id)owner;This method is the more straightforward API to load a gsmarkup file. fileName should be a file name (including the .gsmarkup extension or not) (not an absolute path, just a file name); owner should be an object provided by the application. Both must not be nil, otherwise the method immediately returns NO. The method first builds a context dictionary containing a single key-value pair, which maps the string NSOwner to the object owner; then, it gets the owner bundle (if the owner object belongs to a bundle), or the main bundle (if the owner object does not belong to a bundle); finally, it invokes the method -loadGSMarkupFile:externalNameTable:withZone: of that bundle to load the gsmarkup file. It uses as zone the owner's zone (but this detail is currently ignored). It returns the result of invoking that method. Localizable strings are by default translated using a table with the same name as the gsmarkup file (extension removed, so that the localizable strings file for test.gsmarkup would be test.strings), from the bundle in which the file is loaded.
+ (NSArray *) localizableStringsInGSMarkupFile: (NSString *)fileName;This method parses the fileName file (which should be an absolute path to a file on disk; if the fileName string does not end with .gsmarkup, this extension is automatically added), and it extracts the list of localizable strings in the file. Each tag knows exactly which strings found in its attributes and contents are localizable; the list of localizable strings is built using this knowledge.
- (void) awakeFromGSMarkupThis method is called on the objects created from a GSMarkup file, and on the file owner (NSOwner), if any, after all connections (outlets etc) have been established. You can implement this method to complete the setup of your objects.
- (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.
In some other cases you may want your gsmarkup file to only contain a single view tag (such as a <vbox>) that you then want to programmatically add to an already existing window. In this case, you need to access the top-level objects using one of the techniques explained above. For example, your gsmarkup file could be:
<?xml version="1.0"?> <!DOCTYPE gsmarkup> <gsmarkup> <objects> <vbox> <button title="Miniaturize" action="performMiniaturize:" /> <button title="Quit" action="terminate:" /> </vbox> </objects> </gsmarkup>
If you want to add the <vbox> from that file to an existing window, you would load it using code such as
NSDictionary *table; NSMutableArray *topLevelObjects = [NSMutableArray array]; NSView *vbox; table = [NSDictionary dictionaryWithObjectsAndKeys: self, @"NSOwner", topLevelObjects, @"NSTopLevelObjects", nil]; [NSBundle loadGSMarkupFile: @"MyFile" externalNameTable: table withZone: [self zone]]; vbox = [topLevelObjects objectAtIndex: 0]; /* Now you can do something with vbox, eg, adding it to a window. */