DFRM tutorial

Example 2: playing with radio buttons

by Dominique Béréziat

Now, we know how to design a simple dialog box containing several buttons. We are going to create one formular containg three radio buttons, i.e. the user can only choose one button among the three one. In addition, we will add two buttons: a first one to validate the user choice and a second one to cancel. The result will be stored a in variable.

#include <windom/dfrm.h>

int main() {
  void *frm;
  int pind, cind;

  ApplInit();
  frm = dfrm_create( 10, TYPE_NORMAL);
  pind = dfrm_new_box( frm, 0, 0, 0, 0);
    cind = dfrm_new_button( frm, TYPE_RBUT, "tea");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
    dfrm_setstate( frm, cind, SELECTED, TRUE);

    cind = dfrm_new_button( frm, TYPE_RBUT, "coffee");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
  
    cind = dfrm_new_button( frm, TYPE_RBUT, "beer");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
  dfrm_add( frm, ROOT, pind, 10, 20, DIR_VERT);

  dfrm_repack( frm);
  dfrm_form( frm, WAT_FORM, "Favorite drink?", TRUE);

  for(;;) EvntWindom(MU_MESAG+MU_KEYBD);
  return 0;
}
 

First step

Similarly to the first example, we create 3 buttons embedded in an invisible box to obtain a correct alignment. We choose now TYPE_RBUT which stands for a radio button.

At this time, we decide the first button should be selected (because it could be a default choice). For that, we use the function dfrm_setstate to manipulate object states.

#include <windom/dfrm.h>
int main() {
  void *frm;
  int pind, cind;

  ApplInit();
  frm = dfrm_create( 10, TYPE_NORMAL);
  pind = dfrm_new_box( frm, 0, 0, 0, 0);
    cind = dfrm_new_button( frm, TYPE_RBUT, "tea");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
    dfrm_setstate( frm, cind, SELECTED, TRUE);

    cind = dfrm_new_button( frm, TYPE_RBUT, "coffee");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
  
    cind = dfrm_new_button( frm, TYPE_RBUT, "beer");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
  dfrm_add( frm, ROOT, pind, 10, 20, DIR_VERT);

  pind = dfrm_new_box( frm, 0, 0, 0, 0);
    cind = dfrm_new_button( frm, TYPE_DBUT, "OK");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
    cind = dfrm_new_button( frm, TYPE_EBUT, "Cancel");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
  dfrm_add( frm, ROOT, pind, 10, 20, DIR_VERT);

  dfrm_repack( frm);
  dfrm_form( frm, WAT_FORM, "Favorite drink?", TRUE);

  for(;;) EvntWindom(MU_MESAG+MU_KEYBD);
  return 0;
}
   

Second step

Next, let us add two buttons, "OK" and "Cancel", to validate of to cancel the User's choice. The first one will be an "default" (TYPE_DBUT) button, i.e. an "exit" button which can be selected using the RETURN key, and the second one an "exit" (TYPE_EBUT) button, i.e. a button which can execute an user function when it is selected. Off course, these two buttons must be embedded in a box in order to obtain to correct alignment with the radio buttons.

#include <windom/dfrm.h>

void ok_clicked( WINDOW *win, int index, int mode) {
  ObjcChange( mode, win, index, ~SELECTED, TRUE);
  ApplWrite( _AESapid, WM_CLOSED, win->handle, 
             0, 0, 0, 0);
}

int main() {
  void *frm;
  int pind, cind;

  ApplInit();
  frm = dfrm_create( 10, TYPE_NORMAL);
  pind = dfrm_new_box( frm, 0, 0, 0, 0);
    cind = dfrm_new_button( frm, TYPE_RBUT, "tea");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
    dfrm_setstate( frm, cind, SELECTED, TRUE);

    cind = dfrm_new_button( frm, TYPE_RBUT, "coffee");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
  
    cind = dfrm_new_button( frm, TYPE_RBUT, "beer");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
  dfrm_add( frm, ROOT, pind, 10, 20, DIR_VERT);

  pind = dfrm_new_box( frm, 0, 0, 0, 0);
    cind = dfrm_new_button( frm, TYPE_DBUT, "OK");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
    dfrm_attach( frm, cind, BIND_FUNC, ok_clicked);
    cind = dfrm_new_button( frm, TYPE_EBUT, "Cancel");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
    dfrm_attach( frm, cind, BIND_FUNC, ok_clicked);
  dfrm_add( frm, ROOT, pind, 10, 20, DIR_VERT);

  dfrm_repack( frm);
  dfrm_form( frm, WAT_FORM, "Favorite drink?", TRUE);

  for(;;) EvntWindom(MU_MESAG+MU_KEYBD);
  return 0;
}
   

Third step

The dialog box is over, we need now to interpret the user events. If you click on Ok or Cancel button, you will see the buttons staying selected. The first thing to do is to catch the event of selecting these button. To this end, we need to define a user function binded to these buttons. The binding between the function and the object is performed using dfrm_attach().

The user function, here ok_clicked, does basically two things: first the object state is set to non-selected, second a GEM signal is emitted requiring the closure of the window (and next the exit of the program because it is the standard behavior of WinDom to terminate when the last window is closed).

#include <windom/dfrm.h>

void ok_clicked( WINDOW *win, int index, int mode, 
  int *data) {
  ObjcChange( mode, win, index, ~SELECTED, TRUE);
  ApplWrite( _AESapid, WM_CLOSED, win->handle, 
             0, 0, 0, 0);
  FormAlert(1,"[1][The user selects button %d][OK]",
    *data);
}

void cancel_clicked( WINDOW *win, int index, int mode) 
{
  ObjcChange( mode, win, index, ~SELECTED, TRUE);
  ApplWrite( _AESapid, WM_CLOSED, win->handle, 
             0, 0, 0, 0);
}

int main() {
  void *frm;
  int pind, cind;
  int rbut = 1;

  ApplInit();
  frm = dfrm_create( 10, TYPE_NORMAL);
  pind = dfrm_new_box( frm, 0, 0, 0, 0);
    cind = dfrm_new_button( frm, TYPE_RBUT, "tea");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);  
    /* The value 1 will be set in rbut when this 
       button will be selected */
    dfrm_attach( frm, cind, BIND_VAR, &rbut, 1);
    /*dfrm_setstate( frm, cind, SELECTED, TRUE);*/

    cind = dfrm_new_button( frm, TYPE_RBUT, "coffee");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
   dfrm_attach( frm, cind, BIND_VAR, &rbut, 2);
  
    cind = dfrm_new_button( frm, TYPE_RBUT, "beer");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
   dfrm_attach( frm, cind, BIND_VAR, &rbut, 3);
  dfrm_add( frm, ROOT, pind, 10, 20, DIR_VERT);

  pind = dfrm_new_box( frm, 0, 0, 0, 0);
    cind = dfrm_new_button( frm, TYPE_DBUT, "OK");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
    dfrm_attach( frm, cind, BIND_FUNC, ok_clicked, 
   &rbut);
    cind = dfrm_new_button( frm, TYPE_EBUT, "Cancel");
    dfrm_add( frm, pind, cind, 10, 10, DIR_HORI);
    dfrm_attach( frm, cind, BIND_FUNC, cancel_clicked);
  dfrm_add( frm, ROOT, pind, 10, 20, DIR_VERT);

  dfrm_repack( frm);
  dfrm_form( frm, WAT_FORM, "Favorite drink?", TRUE);

  for(;;) EvntWindom(MU_MESAG+MU_KEYBD);
  return 0;
}
   

Last step

We also want to know which radio button the user has chosen. For that, to bind the three radio button to a unique variable. When the user selects a radio button, the specific value, identifying the button is put to the variable. The binding is perform again with the dfrm_attach function. When the interaction with is user finish, one can read in the variable the final user's choice.

The call to dfrm_setstate() must be removed because WinDom will select the radio button with respect to the value read in the binded variable. Here, the first radio button will be selected because rbut is initialized to 1 and 1 is the value which is affected to rbut if the first button is selected.

User function ok_clicked() is modified to get the final value chosen: the variable rbut may be given to the user function. A cancel_clicked() function is introduced which is basically the previous version of ok_clicked().

Dominique Béréziat