import Data.IORef
import Control.Monad
import Graphics.UI.Gtk
import System.Directory
import Data.Binding.List
import Graphics.UI.Gtk.Binding
data Person = Person {name::String, age::Int, active::Bool} deriving (Read, Show)
main = do --create an input file if none exists
doesFileExist "in.txt" >>= (`unless` writeFile "in.txt"
"[Person {name = \"Joe\", age = 32, active = True},Person {name = \"Fred\", age = 50, active = False},Person {name = \"Alice\", age = 43, active = True}]")
--read the input
f <- readFile "in.txt"
bl <- toBindingList $ read f :: IO (BindingList IORef Person)
--create widgits
initGUI
name' <- entryNew
age' <- spinButtonNewWithRange 0 120 1
active' <- checkButtonNew
--bind them
nav <- navigation bl $ Person "" 0 False
bindControl bl name name' entryText (\p n -> p {name = n})
bindControl bl (fromIntegral . age) age' spinButtonValue (\p a -> p {age = round a})
bindControl bl active active' toggleButtonActive (\p a -> p {active = a})
--arrange the widgits
table <- tableNew 3 2 True
zipWithM_ (\cap row -> do label <- labelNew $ Just cap
tableAttachDefaults table label 0 1 row (row+1))
["Name:", "Age:", "Active:"] [0..2]
zipWithM_ (\wid row -> tableAttachDefaults table wid 1 2 row (row+1))
[toWidget name', toWidget age', toWidget active'] [0..2]
vBox <- vBoxNew False 0
boxPackStartDefaults vBox table
boxPackStartDefaults vBox nav
--create the main window
window <- windowNew
set window [containerChild := vBox, windowTitle := "Data Binding with Gtk2Hs"]
onDestroy window mainQuit
--start the application
widgetShowAll window
mainGUI
new <- fromBindingList bl
writeFile "out.txt" $ show new