Tutorial 2 - Menu hello

This tutorial introduces menus with the "Menu hello" program. The program also consists of a window with the words "Hello world" displayed. A menubar has been added that allow the user to change the displayed string to "Goodbye cruel world!". It is made up of three files - the source and header for the object that contains the window, and the source that contains the function main.

The MenuHelloDir object - MenuHelloDir.cc and MenuHelloDir.h

The object that holds the window is a MenuHelloDir object which is derived from JXWindowDirector.
 

MenuHelloDir source file:

/******************************************************************************
 MenuHelloDir.cc

    BASE CLASS = JXWindowDirector

    Written by Glenn Bach - 1997.

 ******************************************************************************/

#include "MenuHelloDir.h"
#include <JXWindow.h>
#include <JXStaticText.h>
#include <JXTextMenu.h>
#include <JXMenuBar.h>
#include <jAssert.h>

// These define the menu title and the menu items.
// The '|' separates menu items.  The complete syntax
// is described in JXTextMenuData.doc in SetMenuItems()
// and ParseMenuItemStr().

static const JCharacter* kTextMenuTitleStr = "Text";
static const JCharacter* kTextMenuStr = 
    "Hello world! | Goodbye cruel world!";
        
enum
{
    kHello = 1,
    kGoodbye
};

/******************************************************************************
 Constructor

 ******************************************************************************/

MenuHelloDir::MenuHelloDir
    (
    JXDirector* supervisor
    )
    :
    JXWindowDirector(supervisor)
{
    BuildWindow();
}

/******************************************************************************
 Destructor

 ******************************************************************************/

MenuHelloDir::~MenuHelloDir()
{
    // We must not delete the widgets because the framework does this
    // automatically.
}

/******************************************************************************
 BuildWindow
        
    This is a convenient and organized way of putting all of the initial 
    elements into a window. This will keep the constructor less cluttered.

 ******************************************************************************/

void
MenuHelloDir::BuildWindow()
{
    // Create the window and give it to the director.
    JXWindow* window = new JXWindow(this, 200,100, "Hello World Program");
    assert( window != NULL );
    SetWindow(window);

    // This sets the minimum and maximum size to be the
    // current size.
    window->LockCurrentSize();

    // Create the menubar so that it stays on top, but expands as the window
    // expands.
    JXMenuBar* menuBar =
    new JXMenuBar(window, JXWidget::kHElastic, JXWidget::kFixedTop,
             0,0, 200,kJXStdMenuBarHeight);
    assert( menuBar != NULL );

    // Attach our menu to the menubar.
    itsTextMenu = menuBar->AppendTextMenu(kTextMenuTitleStr);

    // Set the menu items in our menu.
    itsTextMenu->SetMenuItems(kTextMenuStr);

    // Set the menu to never disable the menu items.
    itsTextMenu->SetUpdateAction(JXMenu::kDisableNone);

    // The director needs to listen to the window for messages. The message
    // we care about is JXMenu::kItemSelected.
    ListenTo(itsTextMenu);

    // Create the object to display the text. This time, we need to keep a
    // pointer to it so we can change the text later.
    itsText =
    new JXStaticText("Hello world!", window,
         JXWidget::kFixedLeft, JXWidget::kFixedTop,
         20, 40, 160, 20);
    assert( itsText != NULL );
}

/******************************************************************************
 Receive (virtual protected)

        Listen for menu selections.

        Inheriting from JBroadcaster allows objects to send messages to
        each other.  To receive messages from an object, one must call
        ListenTo(), as we did in BuildWindow().  Messages are delivered
        via the Receive() function.  One must always remember to check
        both the sender and the message type before taking any action.

        One must always remember to pass unhandled messages to the
        base class Receive() function so that it can process the messages
        it needs, too.

 ******************************************************************************/

void
MenuHelloDir::Receive
    (
    JBroadcaster*   sender,
    const Message&  message
    )
{
        // Check to see if our menu is broadcasting a message. It simply
        // broadcasts to everyone who is listening (via "ListenTo(...)")
    if (sender == itsTextMenu && message.Is(JXMenu::kItemSelected))
         {

         // We need to cast the sender in order to get access to its
         // member function - GetIndex() in this case.
         const JXMenu::ItemSelected* selection =
          dynamic_cast(const JXMenu::ItemSelected*, &message);
         assert( selection != NULL );

         // Pass the index to a menu handler function
         HandleTextMenu(selection->GetIndex());
         }

        // If we don't handle the message, we need to pass it to the base class
    else
         {
         JXWindowDirector::Receive(sender,message);
         }
}

/******************************************************************************
 HandleTextMenu

        Respond when a menu item has been selected

 ******************************************************************************/

void
MenuHelloDir::HandleTextMenu
    (
    const JIndex index
    )
{
        // Check to see which menu item was selected, and set the text accordingly
    if (index == kHello)
         {
         itsText->SetText("Hello world!");
         }

    else if (index == kGoodbye)
         {
         itsText->SetText("Goodbye cruel world!");
         }
}

MenuHelloDir header file:

/******************************************************************************
 MenuHelloDir.h

    Interface for the MenuHelloDir class

    Written by Glenn Bach - 1997.

 ******************************************************************************/

#ifndef _H_MenuHelloDir
#define _H_MenuHelloDir

#include <JXWindowDirector.h>

class JXStaticText;
class JXTextMenu;

class MenuHelloDir : public JXWindowDirector
{
public:

    MenuHelloDir(JXDirector* supervisor);

    virtual ~MenuHelloDir();

protected:

    virtual void    Receive(JBroadcaster* sender, const Message& message);

private:

    JXStaticText* itsText;
    JXTextMenu* itsTextMenu;

private:

    void BuildWindow();
    void HandleTextMenu(const JIndex index);

    // not allowed

    MenuHelloDir(const MenuHelloDir& source);
    const MenuHelloDir& operator=(const MenuHelloDir& source);
};

#endif

The function main - menu_hello.cc

The application and window director objects are created here, and the application is run.
/******************************************************************************
 menu_hello.cc
 
 Written by Glenn Bach - 1997.

 ******************************************************************************/

#include "MenuHelloDir.h"
#include <JXApplication.h>
#include <jAssert.h>

/******************************************************************************
 main

 ******************************************************************************/

int
main
    (
    int     argc,
    char*   argv[]
    )
{
    // Create the application object - there should only be one of these
    JXApplication* app = new JXApplication(&argc, argv);
    assert( app != NULL );

    // Create the window director to maintain the Hello World window
    MenuHelloDir* mainDir = new MenuHelloDir(app);
    assert( mainDir != NULL );

    // Show the window and activate it
    mainDir->Activate();
        
    // Start the event loop
    app->Run();               
    return 0;
}