Graphical User Interface Example (3)

This third example shows how a Ggi plot window can be used. It is a tested program, which you can extract from this page, compile and run. It then should produce a window like this:

(Sorry, image cannot be displayed) The active elements in this program are two text input fields, two analog valuators and a QUIT button.

The text fields and valuators produce the parameters A and B  which are used in the evaluation of the expression A*sin(B*x). Every time a parameter is changed, the corresponding graph is drawn. (After any previous graph is erased.)

Drawing is done in so-called XOR-mode. This facilitates erasing previous graphs: the graph is erased by simply drawing it again.

As an exercise you might want to replace the function by an other one with more parameters. Or you can add a menu which enables the user to choose the graph's colour.

The next example shows how cursor interaction can be added to the plot field.

Example program:

/* example3.c -XT */

#define  NPTS 100

#include "stddef.h"
#include "math.h"
#include "gipsyc.h"
#include "cmain.h"
#include "init.h"
#include "finis.h"
#include "userfio.h"
#include "pgplot.h"
#include "ggi.h"

static float a=1.0, b=1.0;
static float xmin=0.0, xmax=6.2831853;
static float ymin=-1.1, ymax=1.1;

/*
 *   Plot initialization routine
 */
static void initplot(char *plotname)
{
   fint zero=0, one=1, green=3;
   
   pgbeg_c(&zero, tofchar(plotname), &one, &one);      /* open plot device */
   pgenv_c(&xmin, &xmax, &ymin, &ymax, &zero, &zero);  /* draw frame       */
   pgsci_c(&green);                                    /* set colour index */
   GgiPlotXor(TRUE);                                   /* XOR plot mode    */
}

/*
 *   Plot drawing routine
 */
static void drawplot(void)
{
   static float xvals[NPTS], yvals[NPTS];
   static bool present=FALSE;
   float incr=(xmax-xmin)/NPTS;
   int   i;
   fint  npts=NPTS;

   if (present) pgline_c(&npts, xvals, yvals);       /* erase previous graph */
   else         present=TRUE;
   for (i=0; i<npts; i++) {
      float x=xmin+i*incr;
      xvals[i] = x;
      yvals[i] = a*sin(b*x);
   }                                                 /* calculate new graph  */
   pgline_c(&npts, xvals, yvals);                    /* draw new graph */
}

/*
 *   Keyword handler for QUIT=
 */
static void quit(ident id, char *key, int code, void *arg)
{
   bool finished=toflog(FALSE);
    
   (void)userflog(&finished, 1, 2, key, " ");
   if (tobool(finished)) {
      cancel_c(tofchar(key));
      finis_c();
   }
}

/*
 *   Keyword handler for both A= and B=
 */
static void number(ident id, char *key, int code, void *parameter)
{
   (void)userfreal((float*)parameter, 1, 2, key, " ");
   drawplot();
}

/*
 *   Main program
 */
MAIN_PROGRAM_ENTRY
{
   ident button, text1, text2, gauge1, gauge2, plot, label;

   init_c();

/*
 *    Specify explicit layout and postponed realization.
 */
   GgiAutoLayout(FALSE);      /* layout  done explicitly by program */
   GgiPostponeRealize(TRUE);  /* show after all elements have been positioned */

/*
 *    Create elements.
 */
   button = GgiButton("QUIT=", "Terminate program");
   text1  = GgiTextField("A=", NULL, 10);
   text2  = GgiTextField("B=", NULL, 10);
   gauge1 = GgiGauge("A=", NULL, 200, -1.0, 1.0);
   gauge2 = GgiGauge("B=", NULL, 200,  0.5, 5.0);
   plot   = GgiPlotField("MYPLOT", 400, 300);
   label  = GgiLabel("y = A*sin(B*x)");

/*
 *    Modify some elements' properties.
 */
   (void)GgiSetLabel(gauge1, " ", 1);      /* suppress gauge's keyword label */
   (void)GgiSetLabel(gauge2, " ", 1);      /* suppress gauge's keyword label */
   
/*
 *    Position the elements.
 */
   GgiSetPosition(button, 0, NULL,   0, NULL);              /* top left */
   GgiSetPosition(plot,   0, NULL,  30, button);      /* right below button */
   GgiSetPosition(label,  -(GgiWidth(plot)+GgiWidth(label))/2, plot,
                          -GgiHeight(plot)-GgiHeight(label)-5, plot);
                                                            /* above plot */
   GgiSetPosition(text1,  0, NULL,  10, plot);              /* below plot */
   GgiSetPosition(gauge1, 0, text1, 10, plot);              /* right of text1 */
   GgiSetPosition(text2,  0, NULL,   0, text1);             /* below text1 */
   GgiSetPosition(gauge2, 0, text2,  0, text1);             /* right of text1 */


/*
 *    Show what has been created until now.
 */
   GgiRealize();

/*
 *    Initialize plot field 
 */
   initplot("MYPLOT");                 /* must be done after GgiRealize call */
   
/*
 *    Register keyword callbacks.
 */
   (void)ScheduleKeyevent(quit,   "QUIT=",   KEYCHANGE, NULL);
   (void)ScheduleKeyevent(number, "A=",      KEYCHANGE, &a);
   (void)ScheduleKeyevent(number, "B=",      KEYCHANGE, &b);
 
/*
 *    Initialize parameters causing first plot te be drawn
 */
   if (!TriggerKey("A=")) wkeyf("A=0.7");  /* use "macro" values if present, */
   if (!TriggerKey("B=")) wkeyf("B=1.0");  /* ... otherwise program defaults */
      
/*
 *    Put things into action.
 */
   MainLoop();
}

Programming GIPSY Maintained by J. P. Terlouw