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,
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.
latin.ml) from working correctly.
latin.ml) shows how to set texts and masks, and how to use the circular buffer. The
latin.mlexample itself provides a drill for the Latin first declension.
bugs report to firstname.lastname@example.org.
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
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.
<chr> means hold the CONTROL key while typing the character
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
Here is a summary of cursor-moving operations, and other editing commands:
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.
In this section, you will learn how to create a plain text editor widget.
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
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:
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
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.
OCaml is a computer language that has very cute features:
Let us assume that you have installed the OCaml compiler in your machine. Then, you can enter the interpreter, in order to type and test a few definitions:
E:\scroll\bed>ocaml Objective Caml version 3.10.0 # let pi= 4.0 *. (atan 1.0);; val pi : float = 3.1415926535897931 # let area r= pi *. r ** 2.0;; val area : float -> float = <fun> # area 50.0;; - : float = 7853.981633974483 #
The shortcomings of this approach are obvious:
To address this shortcomings, OCaml distribution is shipped with a compiler. Therefore, you can prepare a file with the source code of your program, and create a command line application.
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.
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:
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.
add receives an input
Wid.getFloatList to compile it into a
list of floats; local function
loop sums up
the list of float; finally, function
procures the string representation of the sum.
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.
This document was translated from LATEX by HEVEA.