Emacs widget: A data entry oriented GUI

Authors: Joao Barbosa de Souza Filho, Reny Cury Filho

Lemac is a simple Graphical User Interface for OCaml; it is based on one of
Elliott Otis's proof of concept (tiny experiment with functional widgets) .
You can download it from here.
The download page offers two kinds of packaging, to wit,

lemac_beta.zip

lemac_beta.tar.gz

Choose the one that fits your needs. For Linux, lemac_beta.tar.gz is better;
lemac_beta.zip is usual in a Windows environment. After deflating the package,
enter the folder lemac_beta and try an example:

ocamlopt graphics.cmxa wid.ml ntxt.ml -o ntxt.exe

If you are in a Windows machine without a C compiler, you may prefer to compile
the example into bytecode:

ocamlc graphics.cma wid.ml ntxt.ml -o ntxt.exe

To test the example, type ntxt.exe from the command line. Now that you certified
that everything is working properly, let us learn the basics of creating and
using a Graphical User Interface, or GUI, for short.

Let us start compiling and running the ready to go examples. Compilation is simple,
as you can see from the following command line:

ocamlopt graphics.cmxa wid.ml ntxt.ml -o ntxt.exe

Figure 1: Edit fields

If you run the program ntxt.exe, you will get a window like the one shown above.
In the example, there are three Emacs like widgets. The first and the second one
are plain text editors. If you click on the tab of the first editor, you can input
text as in the real Emacs. Commands involve the CONTROL key or the META key.
C-<chr> means hold the CONTROL key while typing the character <chr>.
Thus, C-f would be: hold the CONTROL key and type f.
Other exemple, if you type M-<chr> means press and release
the ESC key, and then type <chr>.
Here is a summary of cursor-moving operations, and other editing commands:

C-f

Move forward a character

C-b

Move backward a character

C-n

Move to next line

C-p

Move to previous line

C-a

Move to beginning of line

C-e

Move to end of line

M-a

Move back to beginning of the text

M-e

Move forward to end of the text

Enter

Newline

M-spac

Sets mark

M-w

Copy text from mark to cursor into the kill-ring

C-w

Delete text from mark to cursor

Besides these commands, you can use C-t to execute a function associated to the editor.
In the example, the function changes the text into uppercase. Another way to trigger
the editor function is to click on the X button at the upper right hand corner of the
editor rectangle. Finally there are buttons that can apply functions to the editor text.
For instance, the buttons uppercase and lowercase do what they mean.

Up to now, you have learned how to use the plain text editor widget. There is also form
widgets, that accept input only into pre-defined fields (see figure 2). If you click the
mouse in one of the fields, the cursor goes to the begining of the field, and is ready to
accept input. There is also a function associated with each form widget. In the present
example, the function calculates the average of the contents of the field, whenever you
press C-t. BTW in order to toggle between the input and the output of the form function,
one must press C-v. As in the plain text editor widget, one can trigger the function
associated with the form widget by pressing the small X-button at the upper right hand
side corner of the form.

The simplest GUI program is indeed simple. One starts by creating an editor and storing
it in the variable ed; the function Wid.mk_edt is used to create the widget; it has an
initial text (in the example, 20 lines filled with spaces), and a function
(String.uppercase). It is a good idea to add an exit button to the application too.
Bothe the editor widget and the exit button must be placed inside a perpetual while loop.
That is about all you need to do in order to create a simple application. You can study
the ntxt.ml example to see how to create forms, and applications with buttons and usefull
active functions.

Emacs and Lemac have a few commands that require two keys to start. Here is a summary of
cursor-moving operations, and other editing commands:

C-x C-s

Save the buffer

C-x C-w

Write buffer to file whose name is given on the mini-buffer. You must
press C-x, then C-w; finally type a file name on the mini-buffer, and press enter. The
editor tab will be changed to the file name. The buffer contents will be saved into
the given file.

A form must have a mask specifying the entry fields. You can create masks using a sequence
of hashes; for instance, the mask (###,###) creates a field to input a Cartesian pair that
represents the center of a circle; on the other hand, the mask ## can be used to input the
radius. Given the description of a mask as a list of strings, the function Wid.the_mask
creates the real mask; the function Wid.mask_fun creates a filter for the mask (the filter will
prevent the nal user from typing text outside the mask). In figure 3, one uses a form to
get the center and the radius of a circle, that function draw_circle will plot on the
windows canvas. The function Wid.get_fields is used to filter the contents of the masks.

You can compile this program, and people interested in finding the
area of a circle can use the resulting application without
installing OCaml; to tell the whole truth, even people who do not
know that OCaml exists can use your program. This kind of compiled
program is called command line application, because you must use
the command line to interact with it. I do like command line
applications, but most people don't. The average computer
user prefer GUI application, where GUI stands for Graphical
User Interface. OCaml has no ready to deploy Graphical User Interface,
but if you need one, there are many ways to go.

You can use GTK, a very popular and portable GUI providing library.
Portable means that you can use GTK on Windows, Linux, or MacIntosh.
However, in order to do it, you must download the lablgtk bindings to GTK.

You can create your GUI in a special script language, like TCL/TK.
OCaml is shipped with a TCL/TK module; therefore you don't need to
download anything in order to opt for this solution.

You can choose another GUI providing library, and write the
necessary bindings to use it.

The problem with GUI providing dynamical libraries is that the person
who will use your program must have the library installed in his/her
machine. For instance, if your application is based on GTK, any
person who wants it must install GTK in his/her computer.
In order to do the installation, the person must find the
installation program in the Internet, download from 6 to 8 MB of
code, and install it. Most people find the installation to
be quite tricky, because one must set a path to the GTK libraries.
Linking the lablgtk bindings is also very difficult, because
you will need a lot of third party libraries.

TCL/TK is much easier than GTK. This does not mean that it is
easy. The person who will use your TCL/TK based application
will need to install TCL/TK in his machine. Most people,
who are not computer wizards, regard finding the right
version of TCL/TK in the internet, and installing it quite
difficult. Yes! One cannot use any version of TCL/TK; one
needs the exact version that was in your machine when
you compiled the application.

In order to overcome the difficulties of interpreted GUI,
J. Barbosa created the Emacs widget. Emacs is a very
popular text editor. The Emacs widget is a device that
provides enough Emacs functionality to perform data
input/output and to interact with the final user of your
application. Here are the features of the Emacs widget:

The library is very small, and very easy to build.
You do not need to run make-files that never work
on Windows, or use libraries that do not exist on Linux.
By the way, you do not need to build the library at
all; you can use the source code, if you prefer.

The person who will use your application will not
need to install any external dynamical library.

The source code is short, and well documented.
Therefore, you can modify the widget to make it fit
your needs.

As everything in life, the Emacs widget has its shortcomings.
While GTK and TCL/TK has a team of dedicated people who
will keep actively developing the libraries and the associated script
languages.

GUI applications are based on metaphors. The idea is
to build a human/machine interface that resembles something
that the final user knows how to deal with. Most GUI
applications use a Control Panel metaphor; this means
that the GUI resembles a control panel, i. e., it
has buttons, keyboards, and displays. The Emacs widget,
on the other hand, uses the document metaphor;
this means the the person that will use your application
will input data using a document and a text editor,
which is the Emacs widget.

Let us consider a very simple problem: Your application
will input a text, and replace it with the uppercase
equivalent.

The program is very simple to understand. From lines 4 to 12,
one defines a function main that will be
executed on line 14. The main function has
a single argument, that is the constant (),
of type unit. On line 5, one opens a
graphic window, where the widgets will reside. On line 6,
one creates the ed Emacs widget, and on line 7 one
creates an exit button. The while-loop that spans from
line 8 to line 12 polls the Emacs widget and the exit button;
line 11 refreshes the graphic window, if user resizes it.

When you create a Emacs widget, as shown on line 6, you
provide a function of type string -> string,
i.e., a function that take a string argument, and returns
a string value. String.uppercase is a function
of such a type; however, it is unlikely that many people
will be interested in an application that does nothing
except producing the uppercase version of a string. To
create a useful applications, you can use compile
construction methods to transform the input string into
a more amenable data structure, like a list of floats, before
processing it; for instance, the program below finds the sum
of a list of floats.

Function add receives an input string,
and uses Wid.getFloatList to compile it into a
list of floats; local function loop sums up
the list of float; finally, function string_of_float
procures the string representation of the sum.

Figure 3: Edit fields

Figure 3 shows how the Graphical User Interface looks
like to the final user. If the user presses the Exit button, s/he
will leave the application. If s/he presses the Type tab,
the application will start the Emacs widget, where one can type
text, like in the real Emacs.