Binding Lua

IUP - Portable User Interface

Lua Binding

Overview

The Lua Binding is an interface between the Lua language and IUP, a portable user-interface system. The main purpose of this package is to provide facilities for constructing IUP dialogs using the Lua language. Abstractions were used to create a programming environment similar to that of object-oriented languages, even though Lua is not one of such languages. The concept of event-oriented programming is broadly used here, because the IUP library is based on this model. Most constructions used in IupLua were strongly based on the corresponding constructions in LED.

System Control

Before running any function from the Lua Binding, you must run the iuplua_open function to initialize the toolkit. This function must be run after a call to function IupOpen. All this is done in C in Lua�s host program.

Example:

int main(void)
{
  IupOpen();
  IupControlsOpen();

  /* Lua 3.2 initialization (could be Lua 4.0 or Lua 5.0) */
  lua_open();   
  lua_iolibopen();
  lua_strlibopen();
  lua_mathlibopen();
  iuplua_open();      /* Initialize Binding Lua */
  controlslua_open(); /* Inicialize CPI controls binding Lua */

  IupMainLoop();
  IupControlsClose();
  IupClose();
  return 0;
}

Generating Applications

To use the Lua Binding, you need to link the program to the IupLua library and to the Lua library. IupLua is available in Lua 3.2 and Lua 5.0.

Simple Attributes

Each interface element is created as a Lua table, and its attributes are indicated as fields in this table. Some of these attributes are directly transferred to IUP, so that any changes made to them immediately reflect on the screen. By means of Lua�s tag method system, attribute values defined in IupLua can be transferred to IUP, being immediately updated. However, not all attributes are transferred to IUP. Some are control attributes, such as handle, which stores the handle of the IUP element, and parent, which stores the object immediately above in the class hierarchy. Attributes that receive strings or numbers as values are immediately transferred to IUP. Other values (such as functions or objects) are stored in IupLua and might receive special treatment (as will be explained later).

For instance, a button can be created as follows (defining a title and the background color):

ok = iupbutton{title = "Ok", bgcolor = "0 255 0"}

Font color can be subsequently changed by modifying the value of attribute fgcolor:

ok.fgcolor = "255 0 0"

Note that the attribute names in C and in IupLua are the same, but in IupLua they can be written in lower case. The names of element creation functions are also in lower case, since they are actually constructors of Lua tables.

Some parameters are required attributes (such as title in buttons). Their types are checked when the element is created. The required parameters are exactly the paremeters that are necessary for the element to be created in C.

Some interface elements contain one or more other elements, as is the case of dialogs, lists and boxes. In such cases, the object�s element list is put together as a vector, that is, the elements are placed one after the other, separated by commas. They can be accessed by indexing the object containing them, as can be seen in this example:

box = iuphbox{bt1, bt2, bt3}
box[1].fgcolor = "255 0 0"         -- changes bt1 foreground color
box[2].fgcolor = caixa[1].fgcolor  -- changes bt2 foreground color

Other Attributes

While the attributes receiving numbers or strings are directly transferred to IUP, attributes receiving other interface objects are not directly transferred, because IUP only accepts strings as a value. The metamethod that transfers attributes to IUP verifies if the attribute value is of a �widget� type, that is, if it is an interface element. If the element already has a name, this name is passed to IUP. If not, a new name is created, associated to the element and passed to IUP as the value of the attribute being defined.

This policy is very useful for associating two interface elements, because you can abstract the fact that IUP uses a string to make associations and imagine the interface element itself is being used.

Callbacks

Some attributes are not directly transferred to IUP. They are either control attributes or attributes in charge of treating the actions associated to objects. Since the use of actions requires registering functions in C to be called when the event occurs, there is a differentiated treatment for such attributes. The IupLua system does not require the creation and registration of C functions for this purpose.

Callbacks of different types of interface events are registered by the library when they are initialized. These default callbacks call methods of the object receiving the event. Each different event calls a different method, which can have a few parameters. The objects are initialized with none of these methods set, so the programmer is in charge of setting them when required. They receive the same parameters as callbacks in C, in the same order, and they can either return a value or not (if no return value is set, the IUP_DEFAULT value is returned). The following example shows the definition of an action for a button.

function ok:action ()
  local aux = self.fgcolor
  self.fgcolor = self.bgcolor
  self.bgcolor = aux
end

Or you can do

function myaction(self)
  ...
end

ok.action = myaction

The IUP API binding

Even though there are sintatic sugars used to handle callbacks and attributes in Lua, most of the functions defined in C are exported to Lua, such as IupSetAttribute, IupGetBrother among others.

Exchanging Values between C and Lua

Each binding to a version of Lua uses different features of the language in order to implement IUP handles (Ihandle) in Lua. Therefore, functions have been created to help exchange references between Lua and C.

To push an Ihandle in Lua's stack, use the function:

iuplua_pushihandle(lua_State *L, Ihandle *n);

In Lua 3.2, the lua_State parameter does not exist.

To receive an Ihandle in a C function called from Lua, just use one of the following functions according to which Lua you are using: lua_getuserdata (Lua 3.2),  lua_touserdata (Lua 4) or lua_unboxpointer in (Lua 5).

In order to bring IUP handles created in C to Lua, the user can give the IUP handle a name by means of IupSetHandle and call in Lua the function IupGetFromC.

Ex:

lua_ihandle = IupGetFromC{"element_name"}

where element_name is the name of the element previously defined with IupSetHandle.

Error Handling

Error handling differ between each Lua version. To keep IupLua's API as compatible as possible, functions have been created to execute Lua code:

int iuplua_dofile(lua_State *L, char *filename);
int iuplua_dostring(lua_State *L, const char *string, const char *chunk_name);

If the given functions are used, in every IupLua version the errors will be reported through the _ERRORMESSAGE function. If this function is not defined by the user, IUP will use its default implementation (shows a dialog with the error message.)

If the user chooses not to use those functions, errors will be handled according to the version of Lua used.

The Architecture Behind IupLua

The Lua API for the IUP system was based on object classes representing the different interface elements. A hierarchy was built among these classes, with the main purpose of reusing code. Code inheritance was implemented precisely as described in the Lua user guide.

The root of this hierarchy is the WIDGET class. It contains the basic procedures for construction, parameter type verification, and allocation of structures for controlling IUP�s interface elements. This class also defines the basic parameters of all classes, such as handle (which stores the handle of the associated IUP element) and parent (used to implement the inheritance mechanism).

Even though almost all classes directly descend from the WIDGET class, some other classes serve as mediators in the tree. This is the case of the COMPOSITION class, located among the composition element classes: IUPHBOX, IUPVBOX and IUPZBOX.

Some classes use part of the code from other classes, when they are very similar. This happens to IUPITEM and IUPTOGGLE, which reuse the code related to the verification of parameter types and to the definition of the action callback in the IUPBUTTON class. Class IUPMULTILINE inherits several characteristics from IUPTEXT, such as the definition of the action callback and the verification of parameter types.

The complete class hierarchy can be represented as follows:

WIDGET
   IUPBUTTON
      IUPITEM
      IUPTOGGLE
   IUPCANVAS
   COMPOSITION
      IUPHBOX
      IUPVBOX
      IUPZBOX
   IUPDIALOG
   IUPFILL
   IUPFRAME
   IUPIMAGE
   IUPLABEL
   IUPLIST
   IUPMENU
   IUPRADIO
   IUPSEPARATOR
   IUPSUBMENU
   IUPTEXT
      IUPMULTILINE

Differences in IupLua5

In IupLua5 we follow the same organization of the Lua libraries using the namespace before all the definitions.

  • All exported functions are accessed only through iup.FunctionName, including control initialization like iup.label.
  • All callbacks in are now access through their exact name in the C API.
  • Numeric definitions where kept in upper case by without the IUP_ prefix, like: iup.DEFAULT.
  • String definitions for values are no longer supported, always use "YES", "NO", "ACENTER", etc.

IupLua3 Examples

  • MultiList - Creates a matrix that allows selection of each line at a time.
  • TableTree - Shows a tree given a Lua table.
  • LabelText - Creates a pair Label-Text.
  • AllFonts - Allows you to easily select a font from all possible IUP fonts.

IupLua Test Application

The distribution files include two executables, one for Lua 3 and one for Lua 5, that you can use to test your Lua code. Both applications have support for all the addicional controls.