GNUstep Developer: Introduction to ProjectCenter and gorm

Copyright (C) 2017 Graham Lee.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the page entitled “GNU Free Documentation License”.

1 About This Guide

This is an introduction to building GNUstep applications in Objective-C with the ProjectCenter and gorm developer tools. You will learn how to create a new application project in ProjectCenter, and develop this project into a four–function calculator.

The guide assumes that you already have GNUstep, ProjectCenter and gorm installed, and that you know how to start ProjectCenter. Please look at the GNUstep instructions (or for Linux distributions, their own documentation) for information on this.

2 Creating Your Project

When you launch ProjectCenter for the first time, the outcome may be a little underwhelming: you see a menu and a Log window (see figure 1). Unlike applications from other environments, GNUstep apps do not generally assume they know what you want to do with them: instead, they wait to be told.


PIC

Figure 1: ProjectCenter’s menu and log window.


From ProjectCenter’s menu, select “Project” then “New...”, to bring up the New Project panel (figure 2). Choose somewhere to save the project, pick the “Application” project type and name the project Clock. Click “OK”, and your new project will open in the Project Browser (figure 3).


PIC

Figure 2: ProjectCenter’s New Project panel.



PIC

Figure 3: Your new Clock project.


You’ll investigate the various collections of files as well as the actions available to you as you build the clock, but feel welcome to go exploring and see what has been created in your project.

3 Displaying the Time

A clock isn’t much of a clock if it doesn’t tell the time, so let’s give the application a user interface to do so. In the Interfaces group in your Clock project, you’ll find a file called Clock.gorm. Double-click on that to open the gorm interface editor. A collection of windows will open as shown in figure 4. While it looks like gorm has two menus, the one marked “Gorm” is its real menu and the one called “Main Menu” is part of your clock’s user interface—it’s the menu for your Clock application.


PIC

Figure 4: The Clock user interface in gorm.


You’ll need somewhere to show the time, so make a window for your Clock app. In gorm’s palette panel, there’s an icon that looks like a little GNUstep window; clicking that brings up the windows palette. Drag a window from that onto your desktop to create a new window for your application.

An icon for the window appears in the Clock.gorm window for your user interface, click that and the window’s attributes are shown in the inspector. To make the clock application more usable, you can edit some of these attributes. Change the window’s title to “Clock”, disable the resize and close controls, and make sure it’s visible at launch time, as shown in figure 5.


PIC

Figure 5: Inspecting the clock’s window.


Add a label to that window, you’ll set that label’s content to the current time. Change the gorm palette panel to show the controls palette, by clicking the icon showing radio controls, a text field and other controls. As the clock output is Clock’s main feature you’ll want to make it obvious, so drag the “System bold” label out of the palette onto your Clock window. Move and resize the label so that it takes up the whole window horizontally, as shown in figure 6. As you move and resize controls in gorm, red guidelines appear to help you leave consistent margins between different controls and the edges of their containers.


PIC

Figure 6: Adding a label to the Clock window.


You can try your interface out now, if you like. Save it from gorm’s Document menu, then from the same menu choose “Test interface”. This doesn’t run your Clock application, but loads the user interface objects you’ve created in gorm into an interface simulator. For now, it won’t be very interesting, sitting there saying “System Bold”. Even a VCR that’s lost its power will say “00:00”, which is at least a time. Quit the test from the “Main Menu (Gorm)” menu and go back to gorm.

4 Showing the current time

You’ll want your clock to actually, y’know, tell the time. This is beyond the capabilities of gorm’s built-in panel of controls and widgets so it’s time to write your own code to do it.

Take a moment now to think about the design of the application from an object–oriented point of view. You’ve already used gorm to create some objects in your application: a window, and a label (which is a special type of text field, as far as GNUstep is concerned). In fact, gorm already created some other objects for you too—a menu and some menu items. None of these is capable of telling the time, but they can display things if you tell them what to display. These objects are views.

GNUstep does include objects that model the concept of time, with names like NSDate and NSCalendar. But there’s nothing in GNUstep that orchestrates them: nothing that says “given this object that represents the time, display the time in that object”. That orchestration is done by a controller, and what you’re going to do now is create a controller for your clock.

In the Clock.gorm window, click on “Classes” to show the class browser, and search for NSObject. A list of the subclasses of NSObject is shown (figure 7), including the AppController class that ProjectCenter created for you (but that we haven’t needed to touch yet).


PIC

Figure 7: The class browser in gorm.


From the “Operations” drop-down, choose “Subclass” to create a new NSObject subclass. The inspector panel will update to show the new class’s attributes and you’ll want to do two things: change the new class’s name from NewClass to ClockController, and add an outlet called timeLabel to give the controller somewhere to display the time, once it knows it. Figure ?? shows the inspector once these changes have been made.


PIC

Figure 8: Your new ClockController class.


A class is a sort of recipe for objects, saying that an object made according to this class’s recipe will have these attributes and behaviours. You make use of that recipe by making an object according to its content: you create an instance of the class. Back in gorm’s class browser, with ClockController selected choose “Instantiate” from the Operations drop-down. Gorm will go back to its Objects view, with a new instance of ClockController appearing alongside the window, menu and other objects (figure 9).


PIC

Figure 9: An instance of ClockController.


The clock controller object needs to be shown where the label is that you want it to display the time in. Click on the instance of ClockController shown in figure 9, then in the Inspector panel choose the Connections inspector. Hold down Control and drag from the ClockController instance to the label. You will see that a green S (for “Source”) appears by the controller, and a purple T (for “Target”) appears by the label, as in figure 10. Choose the timeLabel outlet in the inspector and click “Connect”.


PIC

Figure 10: Connecting the controller’s timeLabel outlet.


Now to tell the ClockController how to find the time so it can update the text label. The first part is to generate the source files for ClockController. Go back to gorm’s Classes view, select ClockController and choose “Create Class Files” from the Operations pull-down. Save the source file as ClockController.m (figure 11) and the header file as ClockController.h, both in the Clock project directory.


PIC

Figure 11: Creating the class files for ClockController.


Now you can go back to ProjectCenter, and tell it about these new files to make ClockController part of the project. Double-click on the “Classes” group in ProjectCenter to bring up the “Add Classes” panel, navigate to ClockController.m and add it to the project. ProjectCenter will automatically add ClockController.h to the “Headers” group. Double-click on ClockController.m to open it in ProjectCenter’s code editor (figure 12).


PIC

Figure 12: Editing the source code for ClockController.


When your ClockController instance is loaded by the application from its gorm file, you want it to find the time and display it in the label. GNUstep will automatically send the -awakeFromNib message1 to objects at the correct time, so add the following code to implement -awakeFromNib.

- (void)awakeFromNib  
{  
  NSDate *now = [NSDate date];  
  NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];  
  [dateFormatter setDateStyle: NSDateFormatterNoStyle];  
  [dateFormatter setTimeStyle: NSDateFormatterMediumStyle];  
  [timeLabel setStringValue:[dateFormatter stringFromDate:now]];  
}

Now you can test your clock out! Build the project from ProjectCenter’s Build panel. Click the screwdriver icon in the project browser to display the Build panel (figure 13) and click the leftmost icon to build the application. All being well, you should see the “Build succeeded” message—if not, check whether you entered the code correctly.


PIC

Figure 13: ProjectCenter’s Build panel.


The switch to the Launch panel (figure 14) by clicking the rocket ship icon in the project browser, then on the Launch icon to start your app. You’ll see figure 15, a clock telling the time!


PIC

Figure 14: ProjectCenter’s Launch panel.



PIC

Figure 15: The running Clock application.


5 Updating the Time

It’s not a very exciting clock, because once it’s launched, the time never changes.2 Your ClockController finds the time and displays it in the label, but it only does it once. It would be better if it did that once every second, so that the display of the time stayed up to date.

In ProjectCenter, navigate to the “Interfaces” group and open ClockController.h in the code editor. Add a method -updateTimeDisplay:, and instance variables3 for a timer and a date formatter. When you have made the changes, ClockController.h will look like this.

#include <AppKit/AppKit.h>  
 
@interface ClockController : NSObject  
{  
  id timeLabel;  
  NSTimer *timer;  
  NSDateFormatter *dateFormatter;  
}  
 
- (void)updateTimeDisplay:(NSTimer *)aTimer;  
@end

Now go back to ClockController.m, where you have a few changes to make. The first is to change -awakeFromNib so that instead of updating the time label itself, it sets up the timer and date formatter, then fires the timer for the first time to ensure the label is showing the current time.

- (void)awakeFromNib  
{  
  dateFormatter = [[NSDateFormatter alloc] init];  
  [dateFormatter setDateStyle: NSDateFormatterNoStyle];  
  [dateFormatter setTimeStyle: NSDateFormatterMediumStyle];  
  timer = [[NSTimer scheduledTimerWithTimeInterval:1  
                                            target:self  
                                          selector:@selector(updateTimeDisplay:)  
                                          userInfo:nil  
                                           repeats:YES] retain];  
  [timer fire];  
}

The next thing to do is to implement the -updateTimeDisplay: method so that the display is updated when the timer fires:

- (void)updateTimeDisplay:(NSTimer *)aTimer  
{  
  NSDate *now = [NSDate date];  
  [timeLabel setStringValue:[dateFormatter stringFromDate:now]];  
}

And finally, implement the -dealloc method to release the instance variables you created in -awakeFromNib.4

- (void)dealloc  
{  
  [timer invalidate];  
  [timer release];  
  [dateFormatter release];  
  [super dealloc];  
}

Build and launch your clock again to see it telling the time live!

6 Summary

You have used the ProjectCenter and gorm applications to build and run a Clock application in GNUstep. You created a custom controller class with an outlet to connect it to the view, and wrote code in Objective-C to discover and display the current time. You used a timer to ensure that the time reported remains up-to-date.

7 Resources

The source code for the Clock application created here is available in its entirety from gs-clock on Bitbucket, under the terms of the GNU General Public License, Version 3.