Nutzeroberflächen in Haskell mit wxWidgets von Dominik Wetzel 15.01.2013 Motivation ● Grafische Oberflächen unbedingt erforderlich in vielen Bereichen ● Vereinfacht Bedienung und Nutzung von Programmen ● Darstellung von Grafiken ● Bibliothek für Haskell: wxHaskell – Nutzt wxWidgets – Derzeit Version 0.90, benötigt wxWidgets 2.9 Abb.1 WxWidgets ● Open Source C++ Bibliothek ● Plattform unabhängig (auch Mobil Bereich) ● Schmaler Wrapper für native GUI­Elemente ● Bindings für viele Programmiersprachen ● Große Community ● Existiert seit 1992 ● Aktuelle Versionen: Stabil 2.8.12 (2009), Entwicklung 2.9.4 (2012) Abb.2 Installation wxHaskell für Linux ● ● ● ● Vorraussetzung: GTK­dev und evtl. OpenGL­dev Pakete, build­essentials bzw. C++ Compiler Sourcen von wxWidgets 2.9 downloaden: http://sourceforge.net/projects/wxwindows/files/2.9.4/ wxWidgets kompilieren und installieren ($ ./configure → $ sudo make install) Installieren von wxHaskell ($ cabal install wx) Bei Fehler: in ~/.cabal/packages/hackage.haskell.org/wxc/0.90.0.4/wxc­0.90.0.4.tar.gz → eljpen.cpp suchen → Zeile 159 *_ref = NULL in _ref = NULL ändern → speichern → nochmal installieren ($ cabal install wx) Schlüsselkomponenten ● ● WxDirect: Zum Generieren von low­level Haskell FFI¹ Bindings (aus speziellen C Headern) Wxc: C Binding für wxWidgets, Basis für wxWidgets Haskell Wrapper (Haskell kann nur zu C linken) ● Wxcore: low­level Haskell Bindings zu wxc ● Wx: higher­level Wrapper um wxcore ● Benötigte Imports: – Graphics.UI.WX – evtl. Graphics.UI.WXCore ¹Foreign Function Interface Komponenten ● ● ● Widgets: Basiskomponenten einer GUI – Windows: Container und Fenster – Controls: Knöpfe, Textfelder usw. Layout: Anordnung der Komponenten Events: Verbindung Widget zu Code, werden durch Nutzerinteraktion ausgelöst Beispielprogramm ● Fenster mit Button zum Schließen module Main where import Graphics.UI.WX main :: IO () main = start hello Abb.I hello :: IO () hello = do f <- frame [text := "Hello!"] quit <- button f [text := "Quit", on command := close f] set f [layout := margin 50 (floatCentre (widget quit))]¹ ¹Quelle: http://www.haskell.org/haskellwiki/WxHaskell/Quick_start Programmstruktur ● ● ● ● ● Ähnlich eines imperativen Programms → Arbeit mit Monaden Main nutzt start: → initialisiert GUI Framework, startet Fenster Eventloop Graphische Objekte haben Properties → werden mit set gesetzt oder initial Properties sind Verbindung von Attribut mit Wert → werden mit := zugeordnet Events werden mit on gesetzt in Attribute umgewandelt Beispiel Typen → Widget w hat Attribute von Typ a ● data Attr w a ● data Event w a → Widget w, Eventhandler vom Typ a ● data Prop w ● start :: IO a -> IO () ● (:=) :: Attr w a -> a -> Prop w ● set :: w -> [Prop w] -> IO () ● get :: w -> Attr w a -> IO a ● on :: Event w a -> Attr w a ● Frame :: [Prop (Frame ())] -> IO (Frame ()) → Attribut bereits Wert zugeordnet Objektorientierung ● ● WxWidgets ist Objektorientiert → Vererbung wird „simuliert“ Zusätzlicher Typparameter: – () → von genau diesem Typ – a → Instanz von dieser Klasse ● text :: Attr (Window a) String ● Frame () = Window (CFrame ()) ● Button () = Window (CControl (CButton ())) Nutzen der Dokumentation ● ● Funktionalität der einzelne Widgets in wxWidgets Dokumentation Aufruf von Funktionen → Klassenname+Widget+Parameter – In wxWidgets: wxTextCtrl.GetLineText(long) : wxString – In wxHaskell: textCtrlGetLineText :: TextCtrl a -> Int -> IO(String) ● Subklassen können Funktionen von Superklassen nutzen – ControlGetLabel :: Control a -> IO(String) kann auch mit TextCtrl aufgerufen werden Quellen ● http://www.haskell.org/haskellwiki/WxHaskell ● http://www.wxwidgets.org/ ● http://en.wikibooks.org/wiki/Haskell/GUI ● ● ● ● Dokumentation für wxHaskell 0.90: http://www.geocities.jp/nahcooo10/wxcore/ http://www.geocities.jp/nahcooo10/wx/ Dokumentation für wxWidgets: http://docs.wxwidgets.org/trunk/ Abb.1: http://www.haskell.org/wikiupload/d/d0/Wxhaskell­black­small.png Abb.2: http://upload.wikimedia.org/wikipedia/commons/b/bb/WxWidgets.svg