The Object I/O Library is a collection of functions and data structures to create Clean programs that have a Graphical User Interface (GUI). The Object I/O Library takes care of all low-level event handling, management of OS resources, and so on. You, the programmer, define the GUI-elements. This is done by glueing the appropriate building blocks that can be found in the Object I/O Library. You can also define your own building blocks. These fit seamlessly with the existing components. The type system of Clean guides you by allowing only legal compositions of components. This implies that it is impossible to write ill-constructed programs. You can customise the behaviour of interactive components by adding functions to them. The evaluation of these functions is handled completely by the Object I/O system, you don't have to do anything for this.
The Object I/O Library 1.2 is a huge library offering the specification of GUI-elements and lightweight processes on a very high level of abstraction yet it results in efficient applications. Below some examples are given that are part of the distribution. A real-world example of an Object I/O application is the Integrated Development Environment, the Clean IDE, which is entirely written in Clean. It is also possible to create your own platform games with Object I/O.
The Object I/O Library 1.2 is currently only available for the Wintel platform. We will make a port of this library to the Mac as well. An earlier version 1.1 is already available for the Macintosh (both PPC and 68k). There are no plans to make a port of version 1.2 for the other platfoms.
To help you create your own GUI programs, the distribution comes with a comprehensive tutorial. In this tutorial the basic ideas are explained. It contains a lot of small examples that illustrate the various aspects of the Object I/O Library. In addition, it contains a chapter that covers the TCP library.
The most important features of the Object I/O Library are:
- Orthogonal treatment of all Graphical User Interface element definitions, including windows, dialogs, buttons, scroll bars and the like;
- Easy composition operators to construct new GUI elements from existing ones;
- You can define your own GUI elements as first class citizens;
- All GUI elements can be added and removed dynamically;
- Interactive processes can be added and removed dynamically;
- Interactive processes have specialised document interfaces, such as MDI and SDI;
- Message passing of arbitrary data and function types;
- Each GUI element can have a private local state;
- Local state can be shared between elements of different device type;
- Programming of GUI elements in an object oriented style;
- Flexible layout handling of controls in windows and dialogues;
- Clipboard handling of text;
- Bitmap handling;
- Timers can be added to other devices as element instance;
Below are a couple of screen dumps of demo applications making use of the Object I/O library. The demos are included in the distribution. If you want to see a bigger example, have a look at the Clean IDE.
Below are some fragments of Clean Object I/O programs to give you an impression of the library's use.
Game of Life
One of the examples that were originally written for the old 0.8 I/O library is the game of life. We have rewritten the example for the Object I/O 1.2 library.
The Options menu for this program is specified as follows:
options = Menu "&Options" (SubMenu "Cell Size" (RadioMenu [ (title (2^i),Nothing,Just (char i),noLS (newsize (2^i))) \\ i<-[0..4] ] 4  ) ) where title size = toString size +++ " * " +++ toString size char i = toChar (fromChar '1'+i)
And this is the menu you will get:
Note that in the code fragment the radio menu elements are summarised by means of a list comprehension. This is one illustration of the fact that all Object I/O GUI components are created dynamically. This gives you as a programmer a lot of expressive power.
Another example that has been rewritten to the Object I/O 1.2 Library is the simple database example. Here is a screenshot of the program in action:
The code that generates the first line of buttons (from DisplQ to SelectAllQ) is defined as follows:
ButtonControl "Dis&plQ" [ ControlFunction (noLS DisplQuery),left,buttonwidth , ControlTip "Show current query fields." ] :+:ButtonControl "Set&Q" [ ControlFunction (noLS SetQuery),buttonwidth , ControlTip "Set current input fields as new query." ] :+:ButtonControl "Searc&hQ" [ ControlFunction (noLS Search),buttonwidth , ControlTip "Search next item matching query." ] :+:ButtonControl "Se&lectAllQ" [ ControlFunction (noLS SelectAll),buttonwidth , ControlTip "Set database content to all items matching query." ]
The definitions have are pretty orthogonal: each control element has a number of mandatory attributes (in this case only the titles) and a list of optional attributes (in this case the behaviour functions, layout position, width, and control tip text). The width of the buttons is defined as:
buttonwidth = ControlWidth (ContentWidth "SelectAllQ")
With this attribute you can specify the width of a control in terms of a content string. You don't have to calculate actual string sizes. This makes your program look right on all platforms. The control tip text attribute gives you access to the platform standard tip text user interface. On the Wintel platform, a small text window appears containing the attribute text when you move the mouse over the control. On the Macintosh platform, something similar happens if the user has turned balloon help on.