Functional Graphical User Interfaces — an Implementation Based on GTK

Functional Graphical User Interfaces — an Implementation Based on GTK

Functional Graphical User Interfaces — An Implementation based on GTK Micha lPa lka June 22, 2007 1 Introduction Graphical user interfaces (GUIs) as we know them today were created over 20 years ago, yet they are still notoriously difficult to implement. Evan a moder- ately complex interface requires a large amount of code to implement it. A study at Adobe [8] has shown that the amount of GUI event handling code reaches 1/3 in many projects and is a source of one-halve of bugs. This indicates that the popular techniques used in implementing GUIs are rather low-level because they require writing much more code that seems to be necessary. Despite numerous attempts at changing it, the usual imperative style of programming based on callbacks is still ubiquitous and all mainstream GUI toolkits are based on it. In that scheme, GUI functionality is implemented using callback routines which are triggered by external events, such as button click, and which manually update the program state along with performing required actions. This causes the GUI code responsible for updates to be split into small pieces scattered over multiple callbacks which operate on the same shared state. What emerges is code that that is very unstructured and is often metaphorically described by the term ‘spaghetti code’. Another problem that contributes to the difficulty of implementing GUIs is the lack of compositionality of code written in the callback style. There is no easy way of connecting two components together as events originating in one of them might require changing the state of the other which can be done by defining the components specifically a priori, or equipping them with complicated callback interfaces. To conquer these problems, we will present a programming model based on explicit modeling of dataflow diagrams. We assert that this representation is more natural and preserves locality of code much better that the callback style. Dataflow computation was found to be cleanly expressible in Haskell where combinator libraries provide means of creating domain-specific languages em- bedded in Haskell. Early efforts to employ dataflow representation of GUIs in Haskell include Fudgets [1] developed by Thomas Hallgren and Magnus Carls- son. Dataflow programming has been chosen as a base for Fudgets because it provided a ‘functional feel’ of programming GUIs. Later, the theme was picked up by the FRP group from Yale University who developed Fran [4], a framework for Functional Reactive Programming which was built around the concept of providing manageable denotational semantics to aid reasoning about 1 the code. Subsequently the framework was refined to be based on Arrows, a framework for encoding dataflow diagrams, and called YAMPA [7]. In order to model reactive systems that dynamically change their structure, a reactive programming framework must provide means of specifying changes to dataflow diagrams that occur over time. To implement this, the FRP frame- works based on Haskell use a concept called switching which means replacing a fragment of the diagram with a new one when a specific event happens. Imple- mentation of switching combinators impose significant constraints on the un- derlying structure of FRP libraries and complicates interaction with imperative GUI libraries. Fran and YAMPA are both general reactive programming libraries and do not contain GUI toolkits, however they serve as a base of several GUI toolkits, the most notable being Fruit [3, 2]. Fruit is an advanced functional GUI toolkit which is developed on top of YAMPA and uses a functional graphics library for drawing widgets. For experts, it supports, among other things, continuous and discrete signals, animation, switching and dynamic collections. Fruit has been adapted to run on top of an imperative GUI toolkit, wxWid- gets, by Bart Robinson in wxFruit [10] project. Running on top of a mainstream GUI toolkit is beneficial because all the widgets do not have to be implemented from scratch. However, interfacing the imperative style of wxWidgets with the functional style of Fruit raised issues that made it difficult to implement switch- ing combinators properly for widgets and reduced the possibility to use wxFruit for creating dynamic GUIs. In this report we present a functional GUI toolkit for Haskell similar to wxFruit, however developed from scratch to be based on GTK+ (called GTK later in the report), another mainstream GUI toolkit. The presented toolkit uses GTK for drawing widgets on the screen as well as for laying them out. Central idea to the toolkit is that its implementation performs actions only in response to external events and remains idle otherwise. Our main contributions are as follows: • Our implementation uses GTK for drawing widgets without giving up switching combinators; we provide a simple switching combinator. It is implemented using a novel technique based on restricted discrete signal types and double-step evaluation which allows for switching GTK widgets. • We provide an efficient way of supporting external data models, or Model- View-Controller separation, for complex data models. It is possible, for instance, to have two text views showing the same buffer and populating changes entered into any of them in an effective manner. Earlier func- tional toolkits did support MVC, however no emphasis was placed on this functionality and efficient propagation of changes was impossible. Our implementation has several limits: • It does not support animated widgets, since the implementation can wake up only in response to user actions. • We do not provide advanced switching combinators. • Layout treatment is limited to hierarchical layout using simple layout com- binators. 2 () String String () simpleTextEntry simpleTextOutput Figure 1: Diagrams of components representing text entries The remainder of the report is structured as follows. Section 2 provides a high-level overview of the toolkit and underlying computation model. Sec- tion 3 presents a more technical description along with a short introduction to Haskell and the Arrows framework useful for understanding the section. Sec- tion 4 presents the selected details from the internals of the toolkit. Section 5 discusses the limitations. Our contributions are located mainly in sections 3.5 and 4. 2 Overview of the toolkit In this section we will informally introduce the computation model that is the foundation of our toolkit by presenting example GUIs built using it. The model closely resembles synchronous dataflow programming. We will be building our GUIs out of components, called signal transformers, which we will connect together to form a diagram which will also be represented by a signal transformer. Each signal transformer represents a widget or a larger fragment of a GUI and contains input and output ports for exchanging data with other parts of the program. We can interact with a signal transformer only by (1) influencing it by feeding it appropriate input and (2) getting information from it by reading its output. This ensures that the functionality of components is well encapsulated with input and output ports being the only interface to them. 2.1 Primitive elements First diagram in Figure 1 illustrates an example primitive component of a GUI, a text field whose purpose is to hold text entered by user. We indicate that simpleTextEntry outputs a string of characters by drawing an outgoing arrow labeled with String. Even though simpleTextEntry doesn’t take any data on input we still add an input port to it for consistency with other components. In this case input has type () which is a type that has only one value and thus yields no information. Programmers with C background may call it ‘void’ while functional programmers will probably pronounce it ‘unit’. As expected, simpleTextEntry outputs the text that the widget holds at the moment. We call input and output of simpleTextEntry continuous signals because they yield values at any given moment of execution. However, all continuous signals are in fact step signals since their values change only on event occurrences and remain constant otherwise. We will need another simple component to display text computed by an ap- plication. The component simpleTextOutput shown in Figure 1 has a signature dual to that of simpleTextEntry that is it takes a String and outputs nothing (()). Note that simpleTextOutput is suitable for output only and that the user is prevented from editing it directly. 3 () String () simpleTextEntry simpleTextOutput Figure 2: Diagram of a simple GUI which accepts a string in the first text field and prints it in the second Figure 3: Actual GUI from Figure 2 2.2 Composite GUIs We can imagine a very simple GUI that we can build using these two compo- nents. Figure 2 shows diagram of a GUI where output of a text entry is fed to another text field. Anything that is entered in the first text field ends up also in the second. The actual window realizing the diagram is shown in Figure 3. This example is a GUI that does no explicit computations on the data; we merely move data around from one widget to another. To process data we introduce a special kind of a signal transformer. For any Haskell function f of type a -> b, which takes a value of type a and returns a value of type b, our toolkit allows the programmer to build a new component, written arr f, that performs the computations of f on its input and delivers the result to its output. Of course arr f has an input port of type a and an output port of type b and it does not exhibit itself as a visible widget. Once we can express arbitrary computations we are ready to present a more complex example. Here we are going to ask the user to provide her first and last name and show a greeting message to her. The function that will create the message has type (String, String) -> String which means that it takes a pair of Strings and returns a String.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    19 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us