An EZwgl program should contain the following components.
EZ.h
.
EZ_Initialize
or EZ_InitializeXrm
.
EZ_CreateWidget
or
EZ_CreateWidgetXrm
.
EZ_AddWidgetCallBack
and EZ_AddEventHandler
.
EZ_DisplayWidget
on your
toplevel widgets.
EZ_EventMainLoop
or
EZ_ServiceEvents
or EZ_WaitAndServiceNextEvent
.
Listed below is a simple "Hello World" program. It demonstrates the steps outlined above for writting an EZwgl application. When run, this program displays a toplevel push button labeled "Hello World". If the widget window is resized, the position of the lable will be adjusted accordingly. If you press the left mouse button (Button1) over the widget window, it exits.
/************************** Example 1 *********************************/
#include "EZ.h" /* the header file */
void cleanExit(EZ_Widget *widget, void *dat) /* push button callback */
{
EZ_Shutdown();/* shutdown EZWGL */
exit(0); /* and exit */
}
main(int argc, char **argv)
{
EZ_Widget *hello;
EZ_Initialize(argc,argv,0); /* initialize EZWGL */
/* create a button and set its foreground red */
hello = EZ_CreateWidget(EZ_WIDGET_NORMAL_BUTTON, NULL,
EZ_LABEL_STRING, "Hello World",
EZ_FOREGROUND, "red",
0);
EZ_AddWidgetCallBack(hello, /* register call back */
EZ_CALLBACK, cleanExit, NULL, 0);
EZ_DisplayWidget(hello); /* show the button */
EZ_EventMainLoop(); /* handle mouse inputs */
}
/************************** Example 1 *********************************/
The one and only header file EZ.h
must be included
in all source files of an EZwgl application.
#include "EZ.h"
This files contains type definitions, symbolic constants and forward declarations needed by all applications.
The first order of business of an EZwgl application is to initialize the EZwgl library. This is achieved by calling
EZ_Initialize(int argc, char **argv, int initGL);
or
EZ_InitializeXrm(char *className, XrmOptionDescRec *optsTable, int noptions, int *argc_in_out, char **argv_in_out, char *fallbackResrc, int initgl);
These two functions parse the command line arguments, opens the X server connection and initialize the internal data structure for EZwgl.
The next two functions are responsible for allocating and initializing widgets.
EZ_Widget *EZ_CreateWidget(int type, EZ_Widget *parent, ...);
EZ_Widget *EZ_CreateWidgetXrm(int type, EZ_Widget *parent, char *instanceName, char *ClassName, ...);
These functions create a widget of the given type and initialize widget using the supplied configuration options. They are also responsible for scanning the resource database and configure the widget according to its resources. Configuration options passed to these two functions can be regarded as fallback resources as they will be overriden by application defaults.
Callbacks and event handlers are the only means that an application interacts with EZ widgets. When the user acts on a widget, e.g. pressing a checkButton, the callbacks or the event handlers for the corresponding widget, if any, will be invoked.
Callbacks and event handlers are registered by using
void EZ_AddWidgetCallBack(EZ_Widget *widget, int which_list, EZ_CallBack callback, void *data,int where); void EZ_AddEventHandler(EZ_Widget *widget, EZ_EventHandler hdlr, void *data, int where);
We have already used callbacks in our first example.
The procedure cleanExit
will be executed when
the left mouse button is pressed and released
over the button.
There are four procedure lists for each widget.
Normal callbacks are invoked when the default action has occured on a widget, e.g., press a push button, a double click on a listbox item or drag a slider button.
Destroy callbacks are invoked at the time a widget is being destroyed. This is useful if your application attaches a complex data structure to a widget, it provides a convenient way to clean up your complex data structure associated with a widget, e.g. free allocated memory.
Motion callbacks are available only for Entry, Slider, Scrollbar, Dial, OptionalEntry, FreeLabel, ListBox, FancyListBox, WorkArea, ListTree, gradient bar, histogram and spread sheet widgets. They are invoked whenever the text changes or the selection of a widget changes or the location of a FreeLabel changes etc.
Event handlers are used to define or alter the behavior of a
widget to user events. Private event handlers are called
before the default event handler. A private event handler may remove
an event it handles by using EZ_RemoveEvent
,
which prevents the event in question from being dispatched
to other handlers, including the default handler.
Normal callbacks, motion callbacks and destroy callbacks have the following prototype:
void callback(EZ_Widget *widget, void *data)
where widget
is the widget that callback
is registered to.
data
is a pointer to a client data that will be passed to
callback
when invoked.
Event handlers have the prototype
void eventHandler(EZ_Widget *widget, void *data, int eType, XEvent *xevent);
where widget
is the widget that eventHandler
is
registered to;
data
is a pointer to a client data that will be passed
to the event handler;
eType
is the internal EZ event type; and xevent
is the pointer to the actual X event, it contains all the information
about the event. Normally, actions of your event handler should be based
on xevent
. However, if your event handler just wants to check
whether a key has been pressed or the the state of a button, you may
find that using eType
is more convenient than
deciphering xevent
.
Once a widget has been created, it can be displayed by invoking
void EZ_DisplayWidget(EZ_Widget *widget);
The first time this function is called on a widget, it performs two tasks:
If it is called on a widget which has been previously
displayed. The behavior depends on whether or not widget
is current viewable. If it is, then this function updates
as necessory the geometry of widget
and updates the
display. If widget
is not currently viewable,
the behavior is the following:
widget
is a toplevel widget, then its window is remapped.
widget
is not a toplevel widget, and one
ancestor of widget
is not viewable, then this function
does nothing visually.
widget
is not a toplevel widget, and all its
ancestors are viewable, then the widget window is remapped.
After an application has created and displayed its widgets, it is ready to process events. There are three routines that can be used for event processing.
void EZ_EventMainLoop(void);
void EZ_ServiceEvents(void)
void EZ_WaitAndServiceNextEvent(void)
The first function is the main event loop. It is an infinite loop that waits and processes user inputs. It will call as necessary the callbacks and event handlers registered with EZ widget library. It never returns.
The second function checks the event queue, processes them if there are any, and returns. This function is useful for the "polling" style programming, especially for interactive graphics applications.
The third function checks the event queue, if there are no events on the queue, it waits for the next event to arrive. It processes the first event on the queue and then returns.