Table of Contents
The Document-base application is a kind of special, but commonly used applications. You can open multiple documents, edit and save each of them. Most text editors belong to the document-base application. The Ink.app in GNUstep is a very good example to look at. Here is the Cocoa document about document-base application. You have to read it first. Otherwise, you probably will not know what I am doing. It looks complicated at the first time. You have to deal with NSDocumentController, NSWindowController, NSDocument and NSWindow. Actually, since I use Gorm to build the NSWindow, and NSDocumentController and NSWindowController are not required to subclass, NSDocument is the only class I have to deal with. That makes everything very easy. In this tutorial, I only make the skeleton of the document-base application. The real functions will be add in the later tutorials.
Now, I have to create the main user interface first. Since it is a document-base application, there is not main window at all. I only need a menu so that users can open, save and close each document. So open Gorm, choose "Document->New Application". Click the window in the Gorm main window, use "Edit->Delete" to delete the window. Drag the menu "Info" and "Document" into the main menu. The main user interface will be like this:
Only the menu, no window.
Next, I need a NSDocumentController. Choose the class "NSDocumentController", use menu "Classes->Instantiate" to make an instance.
The main user interface is done. Save to as "Money.gorm".
NSDocumentController will look at the property list of this application in order to know what kind of document it should handle. Here is an example of propery list.
MoneyInfo.plist
{
ApplicationDescription = "Money";
ApplicationIcon = "";
ApplicationName = Money;
ApplicationRelease = 0.1;
Authors = "";
Copyright = "Copyright (C) 200x by ...";
CopyrightDescription = "Released under...";
FullVersionID = 0.1;
URL = "";
NSTypes = (
{
NSName = "mon";
NSHumanReadableName = "Money Document";
NSUnixExtensions = ("mon");
NSRole = Editor;
NSDocumentClass = Document;
}
);
}
The important part is that NSTypes define what kind of document it should handle, and what class to call. In this case, it is class "Document", which I haven't implement yet. This is a simplified property list, but it works. Look at the InkInfo.plist as a better one.
Now, I need to make the class "Document" as the property indicates, and the window for each document. Open Gorm, choose "Document->New Empty". Drag a window out of the palettes. Since this tutorial is only the skeleton, I do nothing in the window.
Look at the classes in the Gorm main window, and use "Classes->Create Subclass" to create a subclass of NSDocument, called "Document".
Don't instantiate it. Instead, it will be the owner of the document window. Click the NSOwner in the Gorm main window, Look at the "Attributes" in the inspector. Choose the "Document" class.
Now, the NSOwner is the class of Document. I need to connect the _window outlet of NSOwner (class "Document") to the window,
and the set the delegate of window to the NSOwner (class "Document").
Finally, use "Classes->Create Class Files" to create the files of class "Document". Save them to Document.m and Document.h. Save the Gorm file into "Document.gorm".
Now, I have Money.gorm, MoneyInfo.plist, Document.h, Document.m and Document.gorm. Five files (Gorm files are actually directories).
NSDocumentController know what class to use because it is written in the property list file. How do NSDocument (or its subclass, "Document") know where the interface of document is ? In this case, the interface of document is Document.gorm. The simple way is to implement the -windowNibName: in NSDocument. The Document files created from Gorm won't work perfectly. Here is the working one:
Document.h:
#import <AppKit/AppKit.h> #import <AppKit/NSDocument.h> @interface Document : NSDocument { } @end
Document.m:
#import "Document.h" @implementation Document - (NSString *) windowNibName { return @"Document.gorm"; } @end
I deleted the extra codes inherited from NSDocument. Include the NSDocument explicitly in the header file because AppKit.h doesn't include it. The most important part is that I return the name of the document interface, "Document.gorm", so that NSDocument can find where the interface are.
Here are the rest of files:
main.m:
#import <AppKit/AppKit.h> int main(int argc, const char *argv[]) { return NSApplicationMain (argc, argv); }
GNUmakefile:
include $(GNUSTEP_MAKEFILES)/common.make APP_NAME = Money Money_HEADERS = Document.h Money_OBJC_FILES = main.m \ Document.m Money_RESOURCE_FILES = MoneyInfo.plist \ Money.gorm \ Document.gorm Money_MAIN_MODEL_FILE = Money.gorm include $(GNUSTEP_MAKEFILES)/application.make
Here is the source code: Money-src.tar.gz
Once the application starts up, you will see only the menu. Use "Document->New" to open a new document. A empty window will show up. You can keep as many documents as you want. The menu items will be automatically enabled depending on the existance of the document. Most menu doesn't work yet.
GNUstep offer a greate framework for document-base applications. Right now, I only need to focus on the Document itself, and don't need to worry about how to manage the multiple documents/windows. GNUstep will handle it perfectly.