module Main where import Graphics.UI.Gtk import Graphics.UI.Gtk.Glade import Data.IORef import qualified CalcModel as Calc main = do initGUI -- load up the glade file calcXmlM <- xmlNew "calc.glade" let calcXml = case calcXmlM of (Just calcXml) -> calcXml Nothing -> error "can't find the glade file \"calc.glade\" \ \in the current directory" -- get a handle on a some widgets from the glade file window <- xmlGetWidget calcXml castToWindow "calcwindow" display <- xmlGetWidget calcXml castToLabel "display" -- a list of the names of the buttons and the actions associated with them let buttonNamesAndOperations = numbericButtons ++ otherButtons numbericButtons = [ ("num-" ++ show n, Calc.enterDigit n) | n <- [0..9] ] otherButtons = [("decimal", Calc.enterDecimalPoint) ,("op-plus", Calc.enterBinOp Calc.plus) ,("op-minus", Calc.enterBinOp Calc.minus) ,("op-times", Calc.enterBinOp Calc.times) ,("op-divide", Calc.enterBinOp Calc.divide) ,("equals", Calc.evaluate) ,("clear", \_ -> Just ("0", Calc.clearCalc))] -- action to do when a button corresponding to a calculator operation gets -- pressed: we update the calculator state and display the new result. -- These calculator operations can return Nothing for when the operation -- makes no sense, we do nothing in this case. calcRef <- newIORef Calc.clearCalc let calcOperation operation = do calc <- readIORef calcRef case operation calc of Nothing -> return () Just (result, calc') -> do display `labelSetLabel` ("" ++ result ++ "") writeIORef calcRef calc' -- get a reference to a button from the glade file and attach the -- handler for when the button is pressed connectButtonToOperation name operation = do button <- xmlGetWidget calcXml castToButton name button `onClicked` calcOperation operation -- connect up all the buttons with their actions. mapM_ (uncurry connectButtonToOperation) buttonNamesAndOperations -- make the program exit when the main window is closed window `onDestroy` mainQuit -- show everything and run the main loop widgetShowAll window mainGUI