# 4.1 - The Basics
Have you ever used a document-based application? I'd bet you have -- document-based applications are one of the most common types of applications. Computers would be useless without them. Document-based applications are applications that interact with documents, such as text files, pictures, videos, and code. Web browsers are also document-based applications. In fact, document-based applications were invented long before computers -- typewriters are essentially document-based applications, and you could argue that pen and paper are also document-based.
OpenStep, and therefore Cocoa and GNUstep, comes with built-in support for document-based applications in its Application Kit. This tutorial won't cover everything you need to know about them -- please read the [*Cocoa document about document-based applications*](https://web.archive.org/web/2004if_/http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/index.html).
Otherwise, you probably will not know what I
am doing.
Document-based apps look complicated at first -- you have to deal with
`NSDocumentController`, `NSWindowController`, `NSDocument` and `NSWindow`.
However, since we'll use Gorm to build the `NSWindow`, and
`NSDocumentController` and `NSWindowController` are not required to
subclass, `NSDocument` is the only class we have to deal with. That makes
everything very easy.
In this section, we only make the skeleton of the
document-based application. We'll add more features in the next part of this tutorial.
## Skeleton user interface
Now, we have to create the main user interface. Since it' i's a
document-based application, there is no main window. We only need
a menu so that users can open, save and close each document.
Open Gorm, choose "Document→New Application". Click the window in the
Gorm main window, use "Edit→Delete" to delete the window. Drag the
menus "Info" and "Document" into the main menu. The main user interface
will be like this:
**Figure 4-32. Menu of document-based application**
![](GSPT_files/Money-01.jpg)
```{note}
Not having a main window can cause problems if you're using a global or local menu bar, rather than a floating menu. Additionally, it's not what users expect except on macOS. We'll address these issues later.
```
Next, I need a `NSDocumentController`. Choose the class
`NSDocumentController`, and use menu item "Classes→Instantiate" to make an
instance.
**Figure 4-33. Create instance of `NSDocumentController`**
![](GSPT_files/Money-02.jpg)
The main user interface is done. Save it 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 the property list we'll be using:
`MoneyInfo.plist`
```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` defines what kinds of documents our application, "Money",
can handle, and what class (which should be a subclass of `NSDocument`) handles the document. In this case, *Money.app* edits "Money Documents" with file extension `.mon`, using the class `Document`, which we haven't implemented yet. This is a simplified property
list, but it works. Look at [`InkInfo.plist`](https://github.com/gnustep/tests-examples/blob/master/gui/Ink/InkInfo.plist) from the *Ink* example application for a better example.
Now, we need to create the class `Document`, and
the window for each document. Open Gorm, choose "Document→New
Empty". Drag a window out of the palettes. We won't do anything in the window yet -- we'll flesh out the UI in the next section.
Look at the classes in the Gorm main window, and use "Classes→Create
Subclass" to create a subclass of `NSDocument`, called `Document`.
**Figure 4-34. Create `NSDocument` subclass**
![](GSPT_files/Money-03.jpg)
Don't instantiate it. Instead, we'll make it the owner of the document
window (in Objects). Click the NSOwner in the Gorm main window, and select the Attributes pane in the inspector. Choose the `Document` class.
**Figure 4-35. Set document as NSOwner of window**
![](GSPT_files/Money-04.jpg)
![](GSPT_files/Money-05.jpg)
Now, the NSOwner is the class of Document. I need to connect the
`_window` outlet of NSOwner (an instance of `Document`) to the window,
**Figure 4-36. Connect NSOwner to window**
![](GSPT_files/Money-06.jpg)
![](GSPT_files/Money-07.jpg)
and the set the delegate of window to the NSOwner (an instance of `Document`).
**Figure 4-37. Connect delegate to NSOwner**
![](GSPT_files/Money-08.jpg)
![](GSPT_files/Money-09.jpg)
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".
## Loading the user interface
Now, we have five files: Money.gorm, MoneyInfo.plist, Document.h, Document.m and
Document.gorm (which is actually a special kind of directory, called a "bundle").
`NSDocumentController` knows what class to use because it is written in the
property list file. How does `NSDocument` (or its subclass, `Document`) know what the document viewer is? In this case, *Money.app*'s document viewer is `Document.gorm`. The simplest way to tell `Document` about `Document.gorm` is to implement the method
`-windowNibName:` in `Document`.
The Document files that Gorm created for us
won't work perfectly. Enter the following code instead:
`Document.h:`
```objc
#import
#import
@interface Document : NSDocument
{
}
@end
```
`Document.m:`
```objc
#import "Document.h"
@implementation Document
- (NSString*) windowNibName {
return @"Document.gorm";
}
@end
```
I deleted the extra code inherited from `NSDocument`. Include
`` explicitly in the header file because `
int main(int argc, const char *argv[]) {
return NSApplicationMain(argc, argv);
}
```
`GNUmakefile:`
```makefile
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](http://gnustep.made-it.com/GSPT/Money/Money-src.tar.gz)
Compile the application with `make`, and run it with `openapp ./Money.app`.
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 offers a great framework for document-based applications. With GNUstep, we 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.