In addition to the usual Cut, Copy, Paste, Delete Select All, this menu also contains:
@itemize @bullet
@item Group @*
Which produces a submenu
@itemize @bullet
@item In Splitview @*
Groups views into an NSSplitView. Gorm does this based on the relative positions of the views being grouped. It determines the orientation and the order of th views and then groups them either vertically or horizontally in the order they appear on the screen.
@item In Box @*
Simply groups all of the views into one NSBox.
@item In ScrollView @*
Simply groups all of the views into one NSScrollView.
@item Ungroup @*
Ungroups the contained views.
@end itemize
@item Set Name @*
This allows the user to set a name for a given object in the Objects view in the main document window.
@item Disable Guideline @*
This item toggles between Enable Guideline and Disable Guideline. This allows the user to turn on or off the guides which appear when placing views in a window or view in Gorm.
Creates a subclass of the currently selected class in the current document classes view.
@item Load Class @*
Loads a class from a .h file into the current document.
@item Create Class Files @*
Generates a .h and .m file from the currently selected class in the current document classes view.
@item Instantiate @*
Creates an instance of the selected class in the current document classes view.
@item Add Outlet/Action @*
Adds an outlet or an action depending on what is selected in the document classes view. If the outlet icon is selected, it will add an outlet, if it the action icon is selected it will add an action.
@item Remove @*
Removes the currently selected outlet, action or class.
@samp{[NSApp -displayConnectionBetween:and:]} to tell Gorm to update its display. This method sets the values currently returned by @samp{[NSApp -connectSource]} and @samp{[NSApp -connectDestination]}.
NSOwner is the class which ``owns'' the interface. This is, by default, NSApplication, but it can be any class you like. You can change it by selecting NSOwner in the document window and going to the ``Custom Class'' inspector in the inspectors window. From there, you should see all of the classes which the NSOwner can assume. We'll discuss more about this later when we go over how to create a new application
@section What is NSFirst?
NSFirst is your interface to the responder chain. NSFirst is representative of the current ``first responder'' in the application. When you want a message, such as a changeFont: message, to go to the current first responder from, say, a menu, you connect the menu item to the NSFirst object in the document window. By doing this, it means that whichever object has first responder status at that time in the application will become the reciever of the ``changeFont:'' message.
The responder chain is a sequence of objects which are called to determine where a message sent to the first responder will go. A message invoked on the first responder will be invoked on the first object in the responder chain which responds to that message.
The object which this message will be called on is determined in the method [NSApplication targetForAction:]. The call sequence is as follows, it will only proceed to the next step in each case if the current step fails to respond to the message which was invoked:
@itemize @bullet
@item The firstResponder of the keyWindow, if one exists.
@item Iterates through all responders by pulling each in the linked list of responders for the key window.
@item It then tries the keyWindow.
@item Then the keyWindow's delegate
@item if the application is document based it tries the document controller object for the key window.
@item then it tries the mainWindow's list of responders (as above)
@item the mainWindow's delegate
@item if the app is document based, it tries the document controller for the main window
@item and finally, it tries the NSApplication delegate.
@end itemize
If all of the options in this list are exhausted, it then gives up and returns nil for the object which is to respond.
@section What is NSFont
NSFont represents the NSFontManager object for the application. This object is a shared singleton. This means that, for any given app, there should be only one instance of the object. This object is generally added to the document window when another objec, such as a Font menu item, is added to the interface, which, in turn, requires that this object be added to the document.
If you have ProjectCenter, you need to open it and create an ``Application'' project. Create it with the name ``FirstApp''. From there you can open the MainMenu.gorm by clicking on interfaces and selecting MainMenu.gorm. If Gorm.app is properly installed, you Gorm should start up.
If you don't have ProjectCenter, you can create the Gorm file by hand. First you need to start Gorm. You can either do this by doing @samp{gopen Gorm.app} from a command line prompt, or you can invoke it from the Dock or from the workspace's file viewer.
You then need to select the @samp{Document} menu, and then @samp{New Application}. This should produce a new document window, with a menu and an empty window. This should be the same as with the ProjectCenter gorm file since this is the basic starting point for an application.
There are two ways to do this next operation. I will take you through each step by step. First click on the classes icon in the toolbar on the top of the Gorm document window. You should see the view below change to an outline view containing a list of class names. Once this happens we're ready to create a class.
Select the class you wish to subclass in the outline view. For our example we will use the simplest: NSObject. Select it by clicking on the class name once. Then go to the Classes menu in the main menu and select Create Subclass (you can also type Alt-Shift-c, which will do this as well. The new class will be created in the list with the name ``NewClass''.
@section Using The Outline View
@cindex Classes Outline View
From here double click on the subclass name to make it editable. Type the name of the class and hit enter. For our example, please use the class name MyController. When you hit enter an alert panel will appear and warn you about breaking connections, simply select OK and continue.
This method of inputting the classes was inspired by IB in OPENSTEP 4.2/Mach which had functionality very similar to this. For users of that the transition to Gorm will be seamless.
@subsection Adding Outlets In The Outline View
Too add an outlet, select the round icon with the two horizontal lines in it (it sort of looks like a wall outlet. This should become depressed. Here you need to go to the Gorm Menu, under Classes select ``Add Outlet/Action''. Each time you press this menu item another outlet will be added with a name similar to newOutlet, as you add more the number at the end will increase. For now add only one outlet.
To rename the outlet simply double click it and change it's name like you did the class above to ``value'' for the sake of our example.
@subsection Adding Actions In the Outline View
The procedure to add on action is precisely the same as adding an outlet, except you must click on the button which looks like a target (a circle with a + inside). Add an action and name it ``buttonPressed:'' for the sake of our example.
@section Using The Class Edit Inspector
@cindex Class Edit Inspector
This way is much more inline with the ``OPENSTEP/GNUstep'' philosophy. For each object there is an inspector, even for Class objects.
Once you have created the class as described in the previous section ``Creating a Class In Gorm'', you must skip to this section to use the inspector. In the Gorm main menu select Tools and then select ``Inspectors''. This will make certain that the inspectors window is being displayed. Once the inspectors window is up move the pulldown on the top to ``Attributes'' and select the class you created which should, at this point, have the name ``NewClass''. You'll notice that the ``Class'' field at the top which shows the name's background color has turned white, instead of grey. This indicates that this class name is editable. Erase ``NewClass'' from the text field and type ``MyController''.
@subsection Adding Outlets In The Inspector
Adding outlets is very intuitive in the inspector. Simply select the ``Outlets'' tab in the tab view and click ``Add'' to add more outlets, and ``Remove'' to remove them. For the sake of our example, add one outlet and name it ``value''.
@subsection Adding Actions In the Inspector
Very much like above only with the ``Actions'' tab, add an action called button pressed.
In the Classes outline view select the new class you've created, now called MyController and then go to the Gorm menu and select Classes, and then Instantiate. The document window should shift from the classes view to the objects view. Amoung the set of objects should be a new object called MyController.
@section Adding Controls from the Palette
Go to the Gorm menu and select Tools, then Palettes. This will bring the palette window to the front. The second palette from the left is the ``ControlsPalette''. Select that one and find the button object (it should have the word ``Button'' in it). Drag that to the window and drop it anywhere you like.
Repeat this operation with the text field. It's the control with ``Text'' in it. We are now ready to start making connections between different objects in the document.
@subsection Making Connections
@cindex Connections
The type of application we are creating is known as a ``NSApplication delegate'' this means that the MyController object will be set as the delegate of NSApplication.
To make this connection click on NSOwner and hold down the Control button, keep it pressed as you drag from the NSOwner object to the MyController object. The inspectors window should change to the Connections inspector and should show two outlets ``delegate'' and ``menu''. Select the ``delegate'', at this point you should see a green S and a purple T on the NSOwner and MyController objects respectively, and press the ``Connect'' button in the inspector. In the ``Connections'' section of the inspector you should see an entry which looks similar to ``delegate (MyController)'' this indicates that the connection has been made.
Now we need to make connections from the controller to the textfield and from the controller to the button. Select the MyController object and Control-Drag (as before) from the object to the text field, this will make an outlet connection. You should see the connections inspector again, this time select the ``value'' outlet and hit Connect.
Next, control-drag from the button to the controller, this will make an action connection. The connections inspector should again appear. This time you need to select the ``target'' outlet, to get the list of actions. The list should have only one entry, which is ``buttonPressed:'' since this is the one we added earlier. Press Connect. You should see an entry like ``buttonPressed: (MyController'' in the Connections section of the inspector.
It is also possible to make this connection to NSFirst, but to keep things simple, make it directly to the object. If you make the connection to buttonPressed: on NSFirst the functionality of the application will be unchanged, but the invocation will take the path described above in the section which describes ``The Responder Chain''.
At this point you must save the .gorm file. Go to the Gorm menu and click Documents and then select ``Save''. If the document was opened from a pre-existing .gorm, it will save to that same file name. If it is an UNTITLED .gorm file a file dialog will appear and you will need to select the directory where you want to store the .gorm file and type the name of the .gorm file.
@section Generating .h and .m files from the class.
This is different than saving, some people have gotten this confused with the idea of Gorm generating the code for the gui. Gorm does nothing of the sort (grin).
Go to the Classes section in the Document window and select the MyController class yet again. Now go to the Gorm menu and select Classes and the select ``Create Class Files''. This will bring up a file panel and it allow you to select the directory in which to put the files. It will first create the MyController.m file and then the MyController.h file. Simply select the directory in which your app will reside and hit okay for both. You can change the names, but the default ones, which are based on the class name, should be sufficient. When you look at the .m for this class, you should see the @samp{buttonPressed:} method with the commecnt @samp{/* insert your code here */} in it. Delete this comment and add @samp{[value setStringValue: @@``Hello''];}. The class should look like this after you're done:
You recall, we connected the textfield to the ``value'' variable. The call above causes the method setStringValue to be invoked on the textfield you added to the window.
Also, note that the name of the method is ``buttonPressed:''. This is the action which is bound to the button. When it is pressed the text in the textfield should change to ``Hello''.
You now need to build the application either by copying in a GNUmakefile and making the appropriate changes or by using ProjectCenter's build capability, depending on if you use it or not.
This app is available as ``SimpleApp'' in the Examples directory under the Documentation directory distributed with Gorm. Hopefully this has helped to demonstrate, albeit on a small scale, the capabilities of Gorm. In later chapters we will cover more advanced application architectures and topics.
This chapter will describe an application, very much like the previous one, but using a slightly different structure. This application uses MyController as the NSOwner of the app instead of making it the delegate of NSApplication.
This application can be viewed as a slight modification of the previous one.
This section will cover some topics which won't be of general interest to most users. The details in this section pertain to the internal workings of Gorm.
@section Gorm file format
The current Gorm file format is basically just a set of objects, encoded one after another in a continuous stream with some markers indicating when a new class starts or which class is encoded.
@subsection The Name Table
Each object in the .gorm file has a name assigned to it by the application. This allows Gorm to refer to the objects by a name once they are loaded rather than an address. Each name is associated with it's object in a dictionary which preserves the overall structure of the GUI which has been created.
This is only used when the user has associated a custom class with an existing instance in the gorm file. If the user has, for instance, added an NSWindow to the gorm, he/she can use the custom class inspector to select a subclass of NSWindow to change to.
This array is used to form the connections after the .gorm file is loaded. The method @samp{[... establishConnection]} is never called on either NSNibControlConnector or NSNibOutletConnector objects. This prevents the connections from having any effect while they are being edited in Gorm itself. Once they are loaded, the establishConnection method is called and the connections are made.