Moon Travel Planner: Displaying Localized Text

According to our specification (see Chapter 2), the Moon Travel Planner application needs a window, Facts for the Traveller, that displays facts about the moon to entice travelers to visit. The list of facts is a perfect candidate for a Localizable.strings file.

You’ll need to do the following to create the window:

  1. Create a new window to display the facts.

  2. Add a text field.

  3. Create a Localizable.strings file and add content for the window.

  4. Write a function to display the text.

  5. Modify the main window event handler so it handles the command that opens the facts window.

  6. Write a handler for the moon facts window. You need this handler to close the window. Later, you’ll need the handler to take care of print commands. (Recall that the specification calls for this window to be printable. You’ll write the printing code in Chapter 9.)

  7. Make sure text displays properly in the window.

Create a New Window

There are two ways you can use Interface Builder to create a new window: add a window to the existing main.nib file or create a new nib file for the window. In this section you’ll add a window to the existing nib file. Later, in Chapter 11 you’ll learn how to create a new nib file for a window.

  1. Double-click the main.nib file in the Moon Travel Planner project.

  2. Create a new window. Click the Windows button in the Palette toolbar. Then drag the window icon from the left side of the palette to the desktop, as shown in Figure 8.4.

  3. Name the window object MoonFacts. This is the name by which you’ll refer to the window in your code. In the Instances pane of the main.nib window, double-click the word “Window” that’s under the icon of the window you just created, type MoonFacts, and press Return. The icon’s name should be the same as that shown in Figure 8.5.

  4. Enter Facts for the Traveler as the window’s title. The title is the text users see in the title bar at the top of the window. With the window active, choose Show Info from the Tools menu, choose Attributes from the pop-up menu at the top of the Info window, type Facts for the Traveler in the Title text field, and press Return.

    A new window dragged from the Windows palette

    Figure 8-4. A new window dragged from the Windows palette

    The MoonFacts icon in the Instances pane

    Figure 8-5. The MoonFacts icon in the Instances pane

  5. Set the window’s class. Choose Document from the Window Class pop-up menu.

  6. Set a Theme Brush for the window. You need to give the window a gray-striped background. Choose Dialog from the Theme Brush pop-up menu.

  7. Set the window’s controls. In the Controls group, make sure Close Box and Collapse Box are the only options selected.

  8. Set the window’s attributes. In the Attributes group, make sure Standard Handler is the only option selected. You can let the operating system handle most of the standard behavior for the window.

  9. Resize the window to 400 by 300 pixels. Choose Size from the pop-up menu at the top of the Show Info window, choose Width/Height from the right Content Rect pop-up menu, and type 400 for width and 300 for height. Then press Return.

Add a Text Field

Although it is possible to display information directly in a window, you’ll add a text field to make the text appear as if it’s framed (see Figure 8.6):

  1. Add a text field to the window. Drag a text field from the Controls palette to the window.

  2. Resize the text field. Drag the text field so it just fits within the Aqua guides, as shown in Figure 8.6.

    Aqua guides showing where to place a text field

    Figure 8-6. Aqua guides showing where to place a text field

  3. Set the signature to MTPP and the text field’s ID to 131. In the Edit Text Info window, choose Control from the pop-up menu. In the Control ID box, type the Moon Travel Planner creator code—MTPP—in the Signature field and 130 in the ID field. Make a note of the ID. When you write code to display text in the text field, you’ll need the text field ID and the signature so the application knows where to draw the text.

  4. Position the window where you’d like it to appear when the user opens it. You should make sure that when the Facts for the Traveler window is open the user can also see the main window, similar to what’s shown in Figure 8.7.

    Windows positioned as they will appear when the application runs

    Figure 8-7. Windows positioned as they will appear when the application runs

  5. Choose Save from the File menu.

Create Content for the Window

You’ll store the text for the window in a Localizable.strings file in the Moon Travel Planner project. As you localize the application for other languages or regions, all you need to do is translate the strings (but not the keys) in the Localizable.strings file.

You need to create a new file and name it Localizable.strings:

  1. Make the Moon Travel Planner project window active. Click the Project Builder icon in the Dock.

  2. Add a Localizable.strings file to your project. Choose New File from the File menu and double-click Empty File. In the dialog that appears, name it Localizable.strings and add the file to the English.lproj folder. The file should automatically appear in the Resources group in your project.

  3. Open the Localizable.strings file. Click Localizable.strings in the Groups & Files list. The empty file opens in the right side of the Project Builder window.

  4. Add a text key and text to the file. Type the following (or make up your own text) into the Localizable.strings file:

    { "Facts" = "Atmosphere: None. Outdoor temperatures range from -173 C to +126 C, so forget the sun block and be sure to pack a pressurized suit. Indoor dress is casual. Raingear optional.
    
    
    Recreation: Golf (miniature and traditional), hiking. No swimming or scuba diving; the Sea of Tranquility doesn't actually contain any water. 
    
    Don't Miss: Apollo 11 landing site. Luna 5 crash landing site. The monolith. 
    
    What to Avoid: I, Clavius, a musical revue history of the moon, showing hourly on the outdoor stage."
    }

    Note the string contains formatting information ( ) to indicate returns.

  5. Save the Moon Travel Planner project.

Write a Function to Display the Window

You need to write code that creates the window from the nib file (main.nib). When a window is created, it is hidden by default. So you also need to write code to show the window when the user chooses Show Facts from the Moon menu and then to hide the window when the user clicks the Close button.

Adding function and global declarations

First, you need to declare the MTPShowMoonFactsWindow function. Copy the following declaration to the main.c file, just after the function declaration for the Compute Travel Time command handler:

pascal void MTPShowMoonFactsWindow (WindowRef window);

You need to declare some global constants to represent the Show Facts menu command and the ID you assigned to the moon facts text box. You’ll also declare a constant to represent the text key—“Facts”—associated with the string in our Localizable.strings file. You assigned the menu command when you created the Moon menu in Chapter 7.

Put these constant declarations in the main file:

#define  kMTPShowMoonFactsCommand       'fAct'
#define  kMTPMoonFactsFieldID           131
#define  kMTPMoonFactsTextKey           "Facts"

You need to declare a window reference for the moon facts window. Modify the declaration for the main window—gMainWindow—so it includes the moon facts window:

WindowRef       gMainWindow,
                gMoonFactsWindow;

Creating the window

You need to add code to the main function so it constructs the interface from the main.nib file you modified in Interface Builder. Copy the following statement to the main function in the main.c file, after the statements that create the main window:

// Create the Facts for the Traveler window err = CreateWindowFromNib (nibRef, CFSTR("MoonFacts"),
                                    &gMoonFactsWindow);
require_noerr (err, CantCreateWindow);

Writing the show moon facts window function

The function MTPShowMoonFactsWindow does the following:

  • Shows the Moon Facts window if it is not visible

  • Expands the window if the window is in the Dock

  • Retrieves a string from the Localizable.strings file and writes it to the window

Copy the function in Example 8.2 to the main program, after the function MTPComputeCommandHandler.

Example 8-2. Show Moon Facts Window Function

pascal void MTPShowMoonFactsWindow (WindowRef window)
{
   CFStringRef      text;
   ControlHandle    moonFactsBox;
   ControlID        moonFactsControlID = {kMTPApplicationSignature, 
                                          kMTPMoonFactsFieldID };
        
   GetControlByID (window, &moonFactsControlID, &moonFactsBox);             //1
   ShowWindow (window);                                                     //2
   SelectWindow (window);
   text = CFCopyLocalizedString (CFSTR(kMTPMoonFactsTextKey),
                                    NULL);                                  //3
   SetControlData (moonFactsBox, 0, kControlEditTextCFStringTag, 
                                sizeof (CFStringRef),
                                &text);                                     //4
   CFRelease (text);                                                        //5
   DrawOneControl (moonFactsBox);                                           //6
 }

Here’s what the function does:

  1. The Control Manager function GetControlByID gets the control handle associated with the text field in which the facts about the moon are displayed.

  2. The Window Manager function ShowWindow makes the window visible. If the window is in the Dock the function expands the window to its normal size.

  3. The Window Manager function SelectWindow makes the window active and frontmost.

  4. The Core Foundation Bundle Services function CFCopyLocalizedString returns the string associated with the kMTPMoonFactsTextKey (“Facts”) from the Localizable.strings file. It returns the result as a reference to a CFString.

  5. The Control Manager function SetControlData sets the moon facts text field to the value of the string, but does not draw the string.

  6. The Core Foundation Base Services function CFRelease releases the memory associated with the CFString object.

  7. The Control Manager function DrawOneControl redraws the moon facts text field with the new string.

Modify the Main Window Event Handler

When a user chooses the Show Facts command from the Moon menu, your application must handle the command by calling the function MTPShowMoonFactsWindow. The main window event handler must take care of the Show Facts command.

You need to add a case to the switch statement to the main window event handler you wrote in Chapter 6 that takes care of the Show Facts command.

Add this code to the switch statement in (MTPMainWindowEventHandler):

case kMTPShowMoonFactsCommand:
        MTPShowMoonFactsWindow (gMoonFactsWindow);
        result = noErr;
        break;

Write a Handler for the Moon Facts Window

You’ve taken all the steps to create a window that shows localized content, and you’ve modified your code so the user can choose a command from the Moon menu to open the window. Now you need to handle the window once it’s open. Recall from Chapter 2 that the user should be able to print the Facts for the Traveller window and set up the page before printing it. So you’ll need to handle those commands. You’ll also need to handle closing the window.

Why not use the standard handler to close the window? When you set up the window attributes for the window, you selected Standard Handler as one of the window’s attributes. The standard handler for the close event disposes of a window when the user clicks the Close button. But because the Moon Travel application creates the Facts for the Traveler window once (when the application opens) and disposes of the window once (when the application quits), the standard close event isn’t appropriate. The Moon Travel Planner application must open and close the Facts for the Traveler window by showing and hiding the window instead of creating and disposing of it. So you’ll need to set up the handler to take care of the window event (kEventClassWindow) that is of the event kind kEventWindowClose.

Note

If your application has windows that require a lot of memory, it’s preferable to dispose of the window when it’s closed and create it again when it needs to be opened.

Now that you know what your handler needs to do, you can go through the same steps you went through to write the main window event handler:

  1. Identify the events the handler takes care of.

  2. Write the code for the handler.

  3. Install the handler.

Identify events

The three events we identified fall into two type of events: command events (setting up and printing the page) and window events (closing the window).

Command events are in the command event class (kEventClassCommand). The specific kind of event in which your application is interested is a process command (kEventProcessCommand). In particular, your handler must take care of the Print and Page Setup commands you added in Chapter 7.

A window close event is in the window event class (kEventClassWindow). The specific kind of event you need to handle is a close event (kEventWindowClose).

You need to declare an event type specification for the two events. As you recall from Chapter 6 an event type is made up of an event class and event kind. You can declare the event type specification by copying the following to the main function, after the EventTypeSpec declaration for mainSpec:

EventTypeSpec  moonSpec[] = {{kEventClassCommand, kEventCommandProcess},
                            {kEventClassWindow, kEventWindowClose}};

Write the code for the handler

The handler for the moon facts window must first check to see which kind of event (window close or process command) it has been given by the Carbon Event Manager. If the kind is a process command event, the handler then needs to check the specific command to see whether it’s Print (pRnt), Page Setup (pGsu), or neither one. If it’s neither, the event gets passed back to the Carbon Event Manager. If it’s Print or Page Setup, the application must call the appropriate function. You’ll write functions that implement setup and printing in Chapter 9.

Before you write the handler, declare it by copying the following to the main.c file, just after the function declaration for the main window event handler:

pascal OSStatus MTPMoonFactsWindowEventHandler (
                                EventHandlerCallRef myHandler,
                                EventRef event, void *userData);

Notice it conforms to the prototype specified in Chapter 6.

You need to declare global constants for the commands you set up in Interface Builder. These are the commands you assigned to the Close, Print, and Page Setup menu commands. Copy the following into the main.c file, just after the constants you’ve already defined for the command IDs:

#define kMTPCloseCommand        'cLse'
#define kMTPPrintCommand        'pRnt'
#define kMTPPageSetupCommand    'pGsu'

Now you can add the handler. Copy the function in Example 8.3 into the main program, after the function MainWindowEventHandler. Make sure you comment out the functions MTPDoPrint and MTPDoPageSetup. You haven’t written those yet, so to build, run, and test the code, you’ll need to have them commented out. You can uncomment them once you’ve added those functions in the next chapter.

Example 8-3. The Moon Facts Window Event Handler

pascal OSStatus MTPMoonFactsWindowEventHandler (
                        EventHandlerCallRef myHandler,
                        EventRef event, void *userData)
{
    OSStatus        result = eventNotHandledErr;
    UInt32          eventKind;
    HICommand       command;
    eventKind = GetEventKind (event);                                  // 1
    switch (eventKind) 
    {
        case kEventWindowClose:                                        // 2
            HideWindow ( (WindowRef) userData);                        // 3
            result =  noErr;
            break;
        case kEventCommandProcess:                                     // 4
            GetEventParameter (event, kEventParamDirectObject,
                    typeHICommand, NULL, sizeof (HICommand), NULL,
                    &command);                                         // 5
             switch (command.commandID)
             {
                case kMTPCloseCommand:                                 // 6
                    HideWindow ( (WindowRef) userData);
                    result = noErr;
                    break;
                case kMTPPrintCommand:
            //      MTPDoPrint (gMoonFactsWindow);                     // 7
                    result = noErr;
                    break;
                case kMTPPageSetupCommand:
            //      MTPDoPageSetup (gMoonFactsWindow);                 // 8
                    result = noErr;
                    break;
            }
        }
   return result;
}

Here’s what the function does:

  1. The Carbon Event Manager function GetEventKind returns the kind of the event.

  2. If the event is a window close event, then it handles it, otherwise it returns the result code eventNotHandledErr to indicate the Carbon Event Manger should handle the event.

  3. The Window Manager function HideWindow hides the Facts for the Traveler window.

  4. If the event is a command process event, you need to figure out exactly which command needs to be handled.

  5. The Carbon Event Manager GetEventParameter gets the command.

  6. If the user chooses Close from the File menu, you’ll call the same functions you would call if the user clicked the Close box.

  7. If the command is a Print command, call MTPDoPrint. This function doesn’t yet exist, so you should comment out the line.

  8. If the command is a Page Setup command, call MTPDoPageSetup. This function doesn’t yet exist, so you should comment out the line.

Install the moon facts window event handler

Just as you did for the main window event handler in Chapter 6 you use the Carbon Event Manager function InstallWindowEventHandler to register the moon facts window event handler. Add the following code to the main function, after the line in which you installed the main window event handler:

InstallWindowEventHandler (gMoonFactsWindow,
            NewEventHandlerUPP (MTPMoonFactsWindowEventHandler),
            2, moonSpec, (void *) gMoonFactsWindow, NULL);

These are the parameters to the function InstallWindowEventHandler:

  • The target of the event handler—in this case, the window to which the handler should be registered, which is the Facts for the Traveler window.

  • A pointer to the window event handler—the function NewEventHandlerUPP returns a pointer to the function you just wrote, MTPMoonFactsWindowEventHandler.

  • The number of events for which the handler is registered, in this case two.

  • A pointer to the event types handled by the event handler—you defined these in the array moonSpec.

  • A value that’s passed to the window event handler when the Carbon Event Manager calls the handler—in this case, a pointer to the window to which the handler is registered, that is, the Facts for the Traveler window.

  • An event handler reference—in this case, NULL.

Make Sure the Text Displays Properly

The function RunApplicationEventLoop is already in your code, in the main function. As long as you’ve commented out the Print and Page Setup functions, you can build and run the application to make sure the window opens and displays the text:

  1. Click the Build button in the upper-left corner of the Moon Travel Planner project window.

  2. Click the Run button in the upper-left corner of the project window.

  3. When the application opens, choose Show Facts from the Moon menu. You should see a window that looks like Figure 8.8.

    A window that displays text read from a Localizable.strings file

    Figure 8-8. A window that displays text read from a Localizable.strings file

  4. Click the Minimize button in the moon facts window. You should see the Facts for the Traveler window shrink and move into the Dock. The standard handler takes care of this.

  5. Click the Facts for the Traveler window icon in the Dock to expand it. The window should expand out of the Dock, to its full size.

  6. Click the Close button in the moon facts window. Your handler takes care of this by hiding the window.

  7. Click Quit in the Moon Travel Planner window.

If the window behaves properly, you’re ready to move on!

Recap

You saw how using language-specific folders for user-readable application properties, help content, interface resources, and strings can facilitate localizing your application. In particular, you looked at using a strings file to store text that will be displayed in a window. You ended the chapter by creating a new window for the Moon Travel Planner application to display facts about the moon, and then reading those facts from the localizable.strings file. In the next chapter you’ll tackle printing.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.74.160