import Control.Concurrent.MVar import Data.IORef import qualified Graphics.UI.Gtk as G data PushButton = PushButton { n_states :: Int , c_state :: Int , labels :: [String] , gtk_button :: G.Button } -- data Dial = Dial mk_pb :: [String] -> IO PushButton mk_pb l = do b <- G.buttonNew G.set b [ G.buttonLabel G.:= l !! 0 ] return (PushButton (length l) 0 l b) pb_incr :: PushButton -> IO PushButton pb_incr (PushButton n i l b) = do let i' = (i + 1) `mod` n G.set b [ G.buttonLabel G.:= l !! i' ] return (PushButton n i' l b) pb_init_r :: PushButton -> IO (IORef PushButton) pb_init_r pb = do let b = gtk_button pb r <- newIORef pb _ <- G.onClicked b (modifyIORef_ r pb_incr) return r pb_init_v :: PushButton -> IO (MVar PushButton) pb_init_v pb = do let b = gtk_button pb v <- newMVar pb _ <- G.onClicked b (modifyMVar_ v pb_incr) return v modifyIORef_ :: IORef a -> (a -> IO a) -> IO () modifyIORef_ ref f = do a <- readIORef ref a' <- f a writeIORef ref a' main :: IO () main = do _ <- G.initGUI w <- G.windowNew c <- G.hBoxNew True 10 G.set w [ G.containerBorderWidth G.:= 10 , G.containerChild G.:= c ] pb_r <- pb_init_r =<< mk_pb ["this", "is", "a", "ref", "test"] b0 <- return . gtk_button =<< readIORef pb_r pb_v <- pb_init_v =<< mk_pb ["this", "is", "an", "mvar", "test"] b1 <- return . gtk_button =<< readMVar pb_v G.set c [ G.containerChild G.:= b0 , G.containerChild G.:= b1 ] _ <- G.onDestroy w G.mainQuit G.widgetShowAll w G.mainGUI