Chapter 13. Money

Table of Contents

Document-base application
Table
Load and Save
Drag and drop in table

Document-base application

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:

Figure 13.1. Menu of document-base application

Menu of document-base application

Only the menu, no window.

Next, I need a NSDocumentController. Choose the class "NSDocumentController", use menu "Classes->Instantiate" to make an instance.

Figure 13.2. Create instance of NSDocumentController

Create instance of NSDocumentController

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".

Figure 13.3. Create NSDocument subclass

Create NSDocument subclass

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.

Figure 13.4. Set document as NSOwner of window

Set document as NSOwner of window
Set document as NSOwner of window

Now, the NSOwner is the class of Document. I need to connect the _window outlet of NSOwner (class "Document") to the window,

Figure 13.5. Connect NSOwner to window

Connect NSOwner to window
Connect NSOwner to window

and the set the delegate of window to the NSOwner (class "Document").

Figure 13.6. Connect delegate to NSOwner

Connect delegate to NSOwner
Connect delegate to NSOwner

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.