Gtk2Hs
An introduction to writing graphical user interfaces in Haskell with Gtk2Hs
Duncan Coutts and Axel Simon
Oxford University Computing Laboratory,
University of Kent at Canterbury Computing Laboratory
Gtk+
- The most popular open source GUI toolkit
- Provides a large and feature-rich set of widgets
- Written in C
- Designed to allow bindings in higher level languages (with garbage collection)
- Single implementation across platforms
(backends for X11, Win32 and others)
[any material that should appear in print but not on the slide]
Gtk+ platform components
UI Building Blocks
Custom Interface Elements
- Gdk: platform-specific drawing and windowing
- Cairo: 2D vector graphics
- Pango: layout and rendering of Unicode text
Under the Hood
- Glib: C-level portability and utility module
- ...and many more
Gtk2Hs
- Bindings for Gtk+, Cairo and parts of Pango and Gdk
- Sanitised, Haskell-friendly interface
- Ensures type safety
- Provides automatic memory management
- Provides some abstraction above the C API
(for example some Gtk+ concepts like attributes and signals
are first class values in the Haskell interface)
Where Gtk2Hs fits in
- Not a “high level” GUI library
- it operates in the IO monad
- Usable for building non-toy applications
- Portable across architectures and platforms
- Well supported
- Good reference documentation
- Usable as a basis for high level GUI libraries
- Future aims:
- to have a more stable API
- to have good introductory tutorials
GUI toolkit concepts
- Event-driven control flow
- Widgets
- Widget attributes
- Events / Signals
- Layout
Event-driven control flow
- We register our interest in particular events
- Blocking call to
mainGUI
- Event loop calls us back when events happen
- Event loop also provides:
Difficulties with event loops
- Inverted control flow
- this makes maintaining state tricky
- can use
IORef
s or MVar
s
- Must not take too long in a callback or the GUI will appear to freeze
- Haskell threads can help with both problems
Widgets
- Stateful objects representing on-screen elements
- Have identity / reference semantics
- Created in the IO monad
window <- windowNew
- Important widgets types:
Widget
- the common interface of all widgets
Container
- various kinds of layout widgets
Window
- top level windows
Hello World
import Graphics.UI.Gtk
main = do
initGUI
window <- windowNew
button <- buttonNew
set window [ windowTitle := "Hello World"
, containerChild := button ]
set button [ buttonLabel := "Hello World" ]
onDestroy window mainQuit
onClicked button $ do
putStrLn "Hello World"
widgetShowAll window
mainGUI
Layout
- Scalable layout rather than fixed positions
- Works by packing widgets into containers
- packing options control how widgets make use of space
- Similar idea to the HTML/CSS model
- Simple layout containers:
- Special layout containers:
Cairo graphics
- High quality 2D vector graphics library
- Multiple backends: screen, PNG, PS and PDF
- Makes use of hardware acceleration if possible
- Allows reusing drawing code for screen and print
- Provides PDF-style drawing model with:
- stroking and filling lines and Bézier curves
- filling using gradients and bitmap patterns
- compositing translucent images
- affine transformations
- anti-aliased text rendering
Drawing widgets using Cairo
Gtk2Hs extensions
There are a few extension packages:
- OpenGL extension allows rendering using HOpenGL
- SVG extension for cairo
- A version of the Haskell School of Expression API
- Mozilla HTML rendering engine in a widget
- "SourceView" - an editor widget with syntax highlighting
- "GConf" - to use the GNOME configuration system