Tutorial 4 - Widget

This tutorial introduces custom widgets with the "Widget" program. The program consists of a window containing a custom widget that is made up of two rectangles. It is made up of five files - the source and header for the object that contains the window, the source and header for the custom widget and the source that contains the function main.

The Widget object - Widget.cc and Widget.h

The custom widget object is called Widget and is derived from JXWidget

Widget source file:

/******************************************************************************
 Widget.cc

    Each area inside a window that displays a particular piece of
    information is an object derived from JXWidget.  To display
    something that is specialized for your particular application,
    you must create a new class derived from JXWidget.

    The minimum requirement for classes derived from JXWidget is that
    they must implement the Draw() and DrawBorder() functions, as
    shown here.

    BASE CLASS = JXWindowDirector

    Written by Glenn Bach - 1997.

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

#include "Widget.h"
#include <JXWidget.h>
#include <JXWindowPainter.h>
#include <JXColormap.h>
#include <jXPainterUtil.h>
#include <jXConstants.h>
#include <jAssert.h>

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

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

Widget::Widget
    (
    JXContainer* enclosure,
    const HSizingOption hSizing,
    const VSizingOption vSizing,
    const JCoordinate x,
    const JCoordinate y,
    const JCoordinate w,
    const JCoordinate h
    )
    :
    JXWidget(enclosure, hSizing, vSizing, x, y, w, h)
{
    // We have to tell JXWidget that we want a border.
    // Only then will DrawBorder() get called.
    SetBorderWidth(kJXDefaultBorderWidth);
}

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

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

Widget::~Widget()
{
}

/******************************************************************************
 Draw

    This gets called by the event loop every time the Widget needs to
    be redrawn.

    p is the Painter that you use to draw to the screen.  The main reason
    for Painter is to hide the system dependent details of drawing,
    and to provide a uniform interface for drawing to the screen, to an
    offscreen image, and to a printer.

    rect is the area that needs to be redrawn.  In simple cases, you
    can just draw everything.  For complex widgets, you often want to
    optimize and only draw the part inside rect.

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

void
Widget::Draw
    (
    JXWindowPainter& p,
    const JRect&     rect
    )
{
    JXColormap* cmap = GetColormap();

    // This is where everything happens
    // See JPainter.h for available functions

    p.SetPenColor(cmap->GetGreenColor());
    p.Rect(10, 10, 50, 50);

    p.SetFilling(kTrue);
    p.SetPenColor(cmap->GetBlueColor());
    p.Rect(10, 70, 50, 50);
}

/******************************************************************************
 DrawBorder

    This gets called by the event loop every time the Widget's border
    needs to be redrawn.

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

void
Widget::DrawBorder
    (
    JXWindowPainter& p,
    const JRect&     frame
    )
{
    JXDrawDownFrame(p, frame, kJXDefaultBorderWidth);
}
 

Widget header file:

/******************************************************************************
 Widget.h

    Interface for the Widget class

    Written by Glenn Bach - 1997.

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

#ifndef _H_Widget
#define _H_Widget

#include <JXWidget.h>

class Widget : public JXWidget
{
public:

    Widget(JXContainer* enclosure,
           const HSizingOption hSizing, const VSizingOption vSizing,
           const JCoordinate x, const JCoordinate y,
           const JCoordinate w, const JCoordinate h);

    virtual ~Widget();

protected:

    virtual void    Draw(JXWindowPainter& p, const JRect& rect);
    virtual void    DrawBorder(JXWindowPainter& p, const JRect& frame);

private:

    // not allowed

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

#endif
 
 

The WidgetDir object - WidgetDir.cc and WidgetDir.h

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

WidgetDir source file:

/******************************************************************************
 WidgetDir.cc

    BASE CLASS = JXWindowDirector

    Written by Glenn Bach - 1997.

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

#include "WidgetDir.h"
#include "Widget.h"
#include <JXWindow.h>
#include <jAssert.h>

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

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

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

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

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

WidgetDir::~WidgetDir()
{
    // Nothing to delete
    // Window is deleted automatically by its director
    // Widget is deleted automatically by its enclosure
}

/******************************************************************************
 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
WidgetDir::BuildWindow()
{
    // Create the window
    JXWindow* window = new JXWindow(this, 300,200, "Test Widget Program");
    assert( window != NULL );

    // Give the window to the director
    SetWindow(window);

    // Set sizing
    window->SetMinSize(300,200);
    window->SetMaxSize(800,600);

    // Create our custom widget
    Widget* widget =
        new Widget(window, JXWidget::kHElastic, JXWidget::kVElastic,
            0, 0, 300, 200);
    assert( widget != NULL );
}
 

WidgetDir header file:

/******************************************************************************
 WidgetDir.h

    Interface for the WidgetDir class

    Written by Glenn Bach - 1997.

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

#ifndef _H_WidgetDir
#define _H_WidgetDir

#include <JXWindowDirector.h>

class WidgetDir : public JXWindowDirector
{
public:

    WidgetDir(JXDirector* supervisor);

    virtual ~WidgetDir();

private:

    void BuildWindow();

    // not allowed

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

#endif
 
 

The function main - widget_main.cc

/******************************************************************************
 widget_main.cc

 Written by Glenn Bach - 1997.

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

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

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

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

int
main
    (
    int      argc,
    char*    argv[]
    )
{
    // Create the application object - one per program
    JXApplication* app = new JXApplication(&argc, argv);
    assert( app != NULL );

    // Create our window director
    WidgetDir* mainDir = new WidgetDir(app);
    assert( mainDir != NULL );

    // Activate the director
    mainDir->Activate();

    // Start the event loop
    app->Run();
    return 0;
}