Difference between revisions of "Grapefruit"
(addition of link to video of HaL 2 talk) |
(updates and improvements) |
||
Line 9: | Line 9: | ||
Grapefruit makes it possible to implement graphical user interfaces by describing them as systems of interconnected components. Components can be visible components like widgets and windows but also invisible components which provide certain control functionality. Component systems can be built from components by using methods from the <hask>Arrow</hask> and <hask>ArrowLoop</hask> classes. |
Grapefruit makes it possible to implement graphical user interfaces by describing them as systems of interconnected components. Components can be visible components like widgets and windows but also invisible components which provide certain control functionality. Component systems can be built from components by using methods from the <hask>Arrow</hask> and <hask>ArrowLoop</hask> classes. |
||
− | Components communicate via signals and event streams. A signal denotes a time-varying value |
+ | Components communicate via signals and event streams. A signal is either continuous or discrete. A continuous signal denotes a time-varying value. A discrete signal denotes a sequence of values assigned to discrete points in time and can therefore be used to model streams of events. Several functions allow the construction of signals in a purely functional manner. |
− | Grapefruit has also support for list signals, special signals denoting time-varying lists where each element has a unique identity. An algebra for list signals provides operations like concatenation, filtering and sorting. The key point is that when the value of a list signal changes, the values of the |
+ | Grapefruit has also support for list signals, special signals denoting time-varying lists where each element has a unique identity. An algebra for list signals provides operations like concatenation, filtering and sorting. The key point is that when the value of a list signal changes, the values of the list signals depending on it do not have to be recalculated completely but can be just updated incrementally. |
User interfaces with a changing collection of widgets are also possible with Grapefruit. There is a special widget which takes a list signal of widgets as its input and always contains the elements of it as its child widgets. |
User interfaces with a changing collection of widgets are also possible with Grapefruit. There is a special widget which takes a list signal of widgets as its input and always contains the elements of it as its child widgets. |
||
− | Furthermore, it is possible to implement animations using graphic signals. These are implemented on top of OpenGL |
+ | Furthermore, it is possible to implement animations using graphic signals. These are implemented on top of OpenGL. So-called caching graphic signals are available to make use of OpenGL’s display lists. |
− | With Grapefruit, user interface descriptions always cover the complete lifetime of the respective interface. No explicit event handler registrations and no explicit recalculations of values are necessary. This is in line with the declarative nature of Haskell because it stresses how the user interface operates instead of how this operation is achieved. Internally though, signals |
+ | With Grapefruit, user interface descriptions always cover the complete lifetime of the respective interface. No explicit event handler registrations and no explicit recalculations of values are necessary. This is in line with the declarative nature of Haskell because it stresses how the user interface operates instead of how this operation is achieved. Internally though, signals are implemented efficiently using the event dispatching and handling mechanism of the underlying GUI toolkit. |
− | The roots of Grapefruit lie in systems like [[Applications_and_libraries/GUI_libraries#FranTk|FranTk]] and [[Applications_and_libraries/GUI_libraries#wxFruit|wxFruit]]. Grapefruit tries to combine concepts of these systems with new ideas to become a system which maintains a reasonable balance between ease of use and efficiency. |
+ | The roots of Grapefruit lie in systems like [[Applications_and_libraries/GUI_libraries#FranTk|FranTk]] and [[Applications_and_libraries/GUI_libraries#wxFruit|wxFruit]]. Grapefruit tries to combine concepts of these systems with new ideas to become a system which maintains a reasonable balance between ease of use and efficiency, and is applicable to real world problems. |
== Status == |
== Status == |
||
− | As of Oktober 2007, Grapefruit is in an early stage. |
+ | As of Oktober 2007, Grapefruit is still in an early stage. Lots of basic concepts are implemented but Grapefruit still lacks a wide variety of widgets, for example. However, adding new widgets shouldn’t be too difficult since Grapefruit provides good generic support for doing this. |
+ | |||
− | * a new signal type for discrete signals which improves and replaces the currently used event stream type |
||
− | * support for the model-view pattern |
||
Furthermore, work on formal specification and verification of GUI properties based on Grapefruit’s GUI programming interface and [[Dependent type|dependent types]] has just started. The proof assistant [[Coq]] will be used in this context. |
Furthermore, work on formal specification and verification of GUI properties based on Grapefruit’s GUI programming interface and [[Dependent type|dependent types]] has just started. The proof assistant [[Coq]] will be used in this context. |
||
Line 34: | Line 33: | ||
== Building == |
== Building == |
||
− | + | Grapefruit uses [[GHC/Type families|type families]]. Therefore, you need a recent version of GHC. Please use GHC 6.8.0.20071030 or newer to avoid problems with nasty GHC bugs of past snapshot versions. |
|
+ | |||
− | # Get and install the binary release of GHC 6.8.0.20070916. |
||
+ | Gtk2Hs 0.9.12 isn’t buildable out of the box with recent GHC snapshots. You should try the following to make it work: |
||
− | # Copy the file <code>extra-gcc-opts</code> from <code>$GHC_SOURCE_DIR</code> to <code>$GHC_INSTALL_DIR/lib/ghc-6.8.0.20070916</code>. (See [http://hackage.haskell.org/trac/ghc/ticket/1703 GHC bug #1703].) |
||
− | # Get the source release of Gtk2Hs 0.9.12. |
||
# Make the following modification to the file <code>configure.ac</code>:<blockquote><p><code>151a152,158<br />> dnl check for a recent ghc-6.7 or later as a proxy for the base package split<br />> GTKHS_PROG_CHECK_VERSION($GHC_VERSION, -ge, 6.7.20070912, [<br />> HAVE_SPLIT_BASE=yes<br />> AC_DEFINE([HAVE_SPLIT_BASE], [1], [Using split base package.])<br />> ])<br />> AM_CONDITIONAL(HAVE_SPLIT_BASE, test "$HAVE_SPLIT_BASE" = "yes")<br />> AC_SUBST(HAVE_SPLIT_BASE)</code></p></blockquote> |
# Make the following modification to the file <code>configure.ac</code>:<blockquote><p><code>151a152,158<br />> dnl check for a recent ghc-6.7 or later as a proxy for the base package split<br />> GTKHS_PROG_CHECK_VERSION($GHC_VERSION, -ge, 6.7.20070912, [<br />> HAVE_SPLIT_BASE=yes<br />> AC_DEFINE([HAVE_SPLIT_BASE], [1], [Using split base package.])<br />> ])<br />> AM_CONDITIONAL(HAVE_SPLIT_BASE, test "$HAVE_SPLIT_BASE" = "yes")<br />> AC_SUBST(HAVE_SPLIT_BASE)</code></p></blockquote> |
||
# Make the following modifications to the file <code>Makefile.am</code>:<blockquote><p><code>125a126,128<br />> if HAVE_SPLIT_BASE<br />> tools_c2hs_c2hsLocal_EXTERNALDEPS += pretty containers array<br />> endif<br />358a362,364<br />> if HAVE_SPLIT_BASE<br />> libHSgtk_a_EXTERNALDEPS += containers array<br />> endif<br />1578a1585,1587<br />> if HAVE_SPLIT_BASE<br />> libHSsoegtk_a_EXTERNALDEPS += old-time<br />> endif</code></p></blockquote> |
# Make the following modifications to the file <code>Makefile.am</code>:<blockquote><p><code>125a126,128<br />> if HAVE_SPLIT_BASE<br />> tools_c2hs_c2hsLocal_EXTERNALDEPS += pretty containers array<br />> endif<br />358a362,364<br />> if HAVE_SPLIT_BASE<br />> libHSgtk_a_EXTERNALDEPS += containers array<br />> endif<br />1578a1585,1587<br />> if HAVE_SPLIT_BASE<br />> libHSsoegtk_a_EXTERNALDEPS += old-time<br />> endif</code></p></blockquote> |
||
# Run <code>autoreconf</code>. |
# Run <code>autoreconf</code>. |
||
# Build and install the library as usual. |
# Build and install the library as usual. |
||
− | |||
− | There is [http://hackage.haskell.org/trac/ghc/ticket/1662 GHC bug #1662] which causes a GHC panic when compiling Haskell code which uses arrow syntax. This causes problems with the Grapefruit examples since they use arrow syntax for describing their GUIs. A solution is to preprocess the example source files in order to get rid of the arrow syntax. However, the arrow preprocessor arrowp as published on [http://www.haskell.org/arrows/download.html] doesn’t seem to be very helpful, at least in our case. The Windows version doesn’t understand infix type constructors which are used in the examples, and the Unix version doesn’t compile. There are two solutions to this problem: |
||
− | # Wolfgang Jeltsch has written a very crude, minimal arrow preprocessor. To make use of it, go into the <code>Haskell</code> directory of the Grapefruit source tree and run <code>runghc CompileExampleCrude.hs ''ExampleName''</code>. The downside of this approach is that the <code>rec</code> keyword is not supported so that the Simple example cannot be compiled. |
||
− | # Matthias Reisner has modified the Windows version of arrowp so that it accepts infix type constructors and compiles under GHC 6.8—on Windows and on Linux. You can download the modified version via [http://softbase.org/grapefruit/utilities/arrowp-reisner.tar.gz]. After adding the directory of the <code>arrowp</code> binary to your search path and moving into the <code>Haskell</code> subdirectory of the Grapefruit distribution, you can compile the examples with <code>runghc CompileExample.hs ''ExampleName''</code>. |
||
== Documentation == |
== Documentation == |
Revision as of 18:44, 30 October 2007
About
Grapefruit is a library for creating graphical user interfaces in a declarative way. It is currently based on Gtk2Hs but implementations on top of other GUI libraries are planned for the future.
Grapefruit makes it possible to implement graphical user interfaces by describing them as systems of interconnected components. Components can be visible components like widgets and windows but also invisible components which provide certain control functionality. Component systems can be built from components by using methods from the Arrow
and ArrowLoop
classes.
Components communicate via signals and event streams. A signal is either continuous or discrete. A continuous signal denotes a time-varying value. A discrete signal denotes a sequence of values assigned to discrete points in time and can therefore be used to model streams of events. Several functions allow the construction of signals in a purely functional manner.
Grapefruit has also support for list signals, special signals denoting time-varying lists where each element has a unique identity. An algebra for list signals provides operations like concatenation, filtering and sorting. The key point is that when the value of a list signal changes, the values of the list signals depending on it do not have to be recalculated completely but can be just updated incrementally.
User interfaces with a changing collection of widgets are also possible with Grapefruit. There is a special widget which takes a list signal of widgets as its input and always contains the elements of it as its child widgets.
Furthermore, it is possible to implement animations using graphic signals. These are implemented on top of OpenGL. So-called caching graphic signals are available to make use of OpenGL’s display lists.
With Grapefruit, user interface descriptions always cover the complete lifetime of the respective interface. No explicit event handler registrations and no explicit recalculations of values are necessary. This is in line with the declarative nature of Haskell because it stresses how the user interface operates instead of how this operation is achieved. Internally though, signals are implemented efficiently using the event dispatching and handling mechanism of the underlying GUI toolkit.
The roots of Grapefruit lie in systems like FranTk and wxFruit. Grapefruit tries to combine concepts of these systems with new ideas to become a system which maintains a reasonable balance between ease of use and efficiency, and is applicable to real world problems.
Status
As of Oktober 2007, Grapefruit is still in an early stage. Lots of basic concepts are implemented but Grapefruit still lacks a wide variety of widgets, for example. However, adding new widgets shouldn’t be too difficult since Grapefruit provides good generic support for doing this.
Furthermore, work on formal specification and verification of GUI properties based on Grapefruit’s GUI programming interface and dependent types has just started. The proof assistant Coq will be used in this context.
Source code
The source code of Grapefruit resides inside a darcs repository under http://softbase.org/grapefruit/darcs/main/. To get a copy, you can use the command darcs get http://softbase.org/grapefruit/darcs/main
.
Building
Grapefruit uses type families. Therefore, you need a recent version of GHC. Please use GHC 6.8.0.20071030 or newer to avoid problems with nasty GHC bugs of past snapshot versions.
Gtk2Hs 0.9.12 isn’t buildable out of the box with recent GHC snapshots. You should try the following to make it work:
- Make the following modification to the file
configure.ac
:151a152,158
> dnl check for a recent ghc-6.7 or later as a proxy for the base package split
> GTKHS_PROG_CHECK_VERSION($GHC_VERSION, -ge, 6.7.20070912, [
> HAVE_SPLIT_BASE=yes
> AC_DEFINE([HAVE_SPLIT_BASE], [1], [Using split base package.])
> ])
> AM_CONDITIONAL(HAVE_SPLIT_BASE, test "$HAVE_SPLIT_BASE" = "yes")
> AC_SUBST(HAVE_SPLIT_BASE) - Make the following modifications to the file
Makefile.am
:125a126,128
> if HAVE_SPLIT_BASE
> tools_c2hs_c2hsLocal_EXTERNALDEPS += pretty containers array
> endif
358a362,364
> if HAVE_SPLIT_BASE
> libHSgtk_a_EXTERNALDEPS += containers array
> endif
1578a1585,1587
> if HAVE_SPLIT_BASE
> libHSsoegtk_a_EXTERNALDEPS += old-time
> endif - Run
autoreconf
. - Build and install the library as usual.
Documentation
There is also documentation generated by Haddock. This documentation comes in two flavors. The API documentation covers only the public interface while the complete documentation covers also the internals. Note that the documentation might be out of date since it is not automatically regenerated on every commit yet.
- Wolfgang Jeltsch: Funktionale GUI-Programmierung in Haskell mit Grapefruit. Haskell in Leipzig 2. July 10, 2007.
Screenshots
Following are some screenshots from example programs using Grapefruit:
- Simple
- Clicking on the button adds a star to the caption of the button. This doesn’t look very meaningful. However, Simple is actually a very important example since it demonstrates that feedbacks work—the output of the button is transformed and then used as the button’s input.
- Codebreaker
- This is a Mastermind™-like game. The Add button is enabled if and only if the input field contains a valid code and the display box is enabled if and only if the list of guesses does not contain the code chosen by the computer. These properties are described in a declarative way in the source code.
- CircuitingObjects
- This example demonstrates Grapefruit’s support for animations.