[ << ] | [ >> ] |  |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

# 2. Getting Started

This chapter introduces the typographical conventions used throughout the manual and then continues with showing a few, simple examples on using the Forms Library. It concludes with a short resumee of the programming model typically found in programs using the library.

## 2.1 Naming Conventions

The names of all Forms Library functions and user-accessible data structures begin with `fl_` or `FL_`, and use an "underscore-between-words" convention, that is when function and variable names are composed of more than one word, an underscore is inserted between each word. For example,

    fl_state
    fl_set_object_label()
    fl_show_form()

All Forms Library macros, constants and types also follow this convention, except that (at least) the first two letters are capitalized. For example,

    FL_min()
    FL_NORMAL_BUTTON
    FL_OBJECT

The term "form" often can be taken to mean a window of your application. But be aware that there are also can be forms that themselves contain further forms, so "form" and "window" aren't necessarily synonyms.

The only exceptions from the above convention are names of functions related to image manipulations - they start with `flimage_`. And then there's a single function called `flps_init()` that allows customization of the way hardcopies are created from an existing user interface.

## 2.2 Some Examples

Before using forms for interaction with the user you first have to define them. Next you can display them and perform interaction with them. Both stages are simple. Before explaining all the details let us first look at some examples. A very simple form definition would look as

    FL_FORM *simpleform;
    simpleform = fl_bgn_form(FL_UP_BOX, 230, 160);
    fl_add_button(FL_NORMAL_BUTTON, 40, 50, 150, 60, "Push Me");
    fl_end_form();

The first line indicates the start of the form definition. `simpleform` will later be used to identify the form. The type of the form is `FL_UP_BOX`. This means that the background of the form is a raised box that looks like it is coming out of the screen. The form has a size of 230 by 160 pixels. Next we add a button to the form. The type of the button is `FL_NORMAL_BUTTON` which will be explained below in detail. It is positioned in the form by virtue of the button geometry supplied and has "Push Me" as its label. After having defined the form we can display it using the call

    fl_show_form(simpleform, FL_PLACE_MOUSE, FL_NOBORDER,
                 "SimpleForm");

This will show the form on the screen at the mouse position. (The third argument indicates whether the form gets window manager's decoration and the fourth is the window title.)

Next we give the control over the interaction to the Forms Library's main event loop by calling

    fl_do_forms();

This will handle interaction with the form until you press and release the button with the mouse, at which moment control is returned to the program. Now the form can be removed from the screen (and have its associated window destroyed) using

    fl_hide_form(simpleform);

The complete program is given in the file ``pushme.c`' in the subdirectory ``demos`'. All demonstration programs can be found in this directory. Studying them is a good way of learning how the library works.

Compile and run it to see the effect. To compile a program using the Forms Library use the following command or something similar

    cc -o pushme pushme.c -lforms

Please note that linking against the Forms library requires some other libraries to be istalled, at least the `X11` and the `Xpm` library. Some applications may also require the `JPEG` and/or the `GL` library. These libraries don't need to be specified explicitely in the linker command but must be available since the Forms library depends on them. If not installed contact your systems administrator.

This simple example is, of course, of little use. Let us look at a slightly more complicated one (the program can be found in ``yesno.c`'.)

    #include <forms.h>

    int main(int argc, char *argv[]) {
        FL_FORM *form;
        FL_OBJECT *yes,
                  *no,
                  *but;

        fl_initialize(&argc, argv, "FormDemo", 0, 0);

        form = fl_bgn_form(FL_UP_BOX, 320, 120);
        fl_add_box(FL_NO_BOX, 160, 40, 0, 0, "Do you want to Quit?");
        yes = fl_add_button(FL_NORMAL_BUTTON, 40, 70, 80, 30, "Yes");
        no  = fl_add_button(FL_NORMAL_BUTTON, 200, 70, 80, 30, "No");
        fl_end_form();

        fl_show_form(form, FL_PLACE_MOUSE, FL_TRANSIENT, "Question");

        while (1) {
            if (fl_do_forms() == yes)
            {
                printf("Yes is pushed\n");
                break;
            }
            else
                printf("No is pushed\n");
        }

        fl_finish();
        return 0;
    }

It creates a form with a simple text and two buttons. After displaying the form `fl_do_forms()` is called. This routine returns the object being pushed. Simply checking whether this is object `yes` or `no` determines whether we should quit.

As you see, the program starts by calling the routine `fl_initialize()`. This routine should be called before any other calls to the library are made (except for `fl_set_defaults()`). One of the things this routine does is to establish a connection to the X server and initialize a resource database used by the X resource manager. It also does many other things, such as parsing command line options and initializing internal Forms Library structures. For now, it suffices to know that by calling this routine, a program automatically recognizes the following command line options

Option | Value type | Meaning
--- | --- | ---
`-display` host:dpy | string | Remote host
`-name` appname | string | change application name
`-visual` class | string | TrueColor, PseudoColor etc.
`-depth` depth | integer | Preferred visual depth
`-private` | none | Force a private colormap
`-shared` | none | Always share colormap
`-stdcmap` | none | Use standard colormap
`-fldebug` level | integer | Print some debug information
`-flhelp` | none | Print out these options
`-sync` | none | Force synchronous mode

Note that the executable name `argv[0]` should not contain period or `*`. See section Overview of Main Functions, for further details. The above program can in fact be made a lot simpler, using the goodies described in Goodies. You can simply write:

    while (!fl_show_question("Do you want to Quit?", 0))
        /* empty */ ;

Except printing out a message telling which button was pressed it will have exactly the same effect.

The above program only shows one of the event handling methods provided by the library. The direct method of event handling shown is appropriate for simple programs. But, obviously, already for a program with just a few nmore objects it would become rather tedious to have to check each time `fl_do_forms()` returns each of those objects to find out which of them was responsible and react accordingly. Utilizing object callback functions is then typically much easier and thus os strongly recommended.

We demonstrate the use of object callbacks using the previous example with some modifications so that event processing via callbacks is utilized. It is recommended and also typical of a good XForms application to separate the UI components and the application program itself. Typically the UI components are generated by the bundled GUI builder and the application program consists mostly of callbacks and some glue code that combines the UI and the program.

To use callbacks, a typical procedure would be to define all the callback functions first, then register them with the system using `fl_set_object_callback()`. After the form is realized (shown), control is handed to Forms Library's main loop `fl_do_forms()`, which responds to user events indefinitely and never returns.

After modifications are made to utilize object callbacks, the simple question example looks as follows:

    #include <stdio.h>
    #include <stdlib.h>
    #include <forms.h>

    void yes_callback(FL_OBJECT *obj, long user_data) {
        printf("Yes is pushed\n");
        fl_finish();
        exit(0);
    }

    void no_callback(FL_OBJECT *obj, long user_data) {
        printf("No is pushed\n");
    }

    int main(int argc, char *argv[]) {
        FL_FORM *form;
        FL_OBJECT *obj;

        fl_initialize(&argc, argv, "FormDemo", 0, 0);

        form = fl_bgn_form(FL_UP_BOX, 320, 120);
        fl_add_box(FL_NO_BOX, 160, 40, 0, 0, "Do you want to Quit?");
        obj = fl_add_button(FL_NORMAL_BUTTON, 40, 70, 80, 30,"Yes");
        fl_set_object_callback(obj, yes_callback, 0);
        obj = fl_add_button(FL_NORMAL_BUTTON, 200, 70, 80, 30,"No");
        fl_set_object_callback(obj, no_callback, 0);
        fl_end_form();

        fl_show_form(form, FL_PLACE_MOUSE, FL_TRANSIENT, "Question");
        fl_do_forms();

        return 0;
    }

In this example, callback routines for both the yes and no buttons are first defined. Then they are registered with the system using `fl_set_object_callback()`. After the form is shown, the event handling is again handed to the main loop in Forms Library via `fl_do_forms()`. In this case, whenever the buttons are pushed, the callback routine is invoked with the object being pushed as the first argument to the callback function, and `fl_do_forms()` never returns.

You might also have noticed that in this example both buttons are made anonymous, that is, it is not possible to reference the buttons outside of the creating routine. This is often desirable when callback functions are bound to objects as the objects themselves will not be referenced except as callback arguments. By creating anonymous objects a program avoids littering itself with useless identifiers.

The callback model presented above is the preferred way of interaction for typical programs and it is strongly recommended that programs using XForms be coded using object callbacks.

## 2.3 Programming Model

To summarize, every Forms Library application program must perform several basic steps. These are

Initialize the Forms Library

  This step establishes a connection to the X server, allocates resources and otherwise initializes the Forms Library's internal structures, which include visual selection, font initialization and command line parsing.

Defining forms

  Every program creates one or more forms and all the objects on them to construct the user interface. This step may also include callback registration and per object initialization such as setting bounds for sliders etc.

Showing forms

  This step makes the designed user interface visible by creating and mapping the window (and subwindows) used by the forms.

Main loop

  Most Forms Library applications are completely event-driven and are designed to respond to user events indefinitely. The Forms Library main loop, usually invoked by calling `fl_do_forms()`, retrieves events from the X event queue, dispatches them to the appropriate objects and notifies the application of what action, if any, should be taken. The actual notification method depends on how the interaction is set up, which could be done by calling an object callback or by returning the object whose status has changed to the application program.

The following chapters will lead you through each step of the process with more details.

[ << ] | [ >> ] |  |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

This document was generated by Jens Thoms Toerring on January 5, 2014 using texi2html 1.82.