-- | controls are widgets that are: -- * specified in the program text, -- * displayed in the GUI, -- * read while executing the program. module Controls where import qualified Program import qualified Module import qualified Rule import qualified Term import qualified Exception import qualified Control.Monad.Exception.Synchronous as Exc import qualified Graphics.UI.WX as WX import qualified Graphics.UI.WXCore.WxcClassesMZ as WXCMZ import Graphics.UI.WX.Attributes ( Prop((:=)), set, get ) import Graphics.UI.WX.Classes import Graphics.UI.WX.Events import Graphics.UI.WX.Layout ( layout, container, row, widget ) import qualified Data.Map as M import Control.Monad ( forM ) import Control.Functor.HT ( void ) data Event = EventBool Term.Identifier Bool deriving Show data Control = CheckBox Bool moduleName :: Module.Name moduleName = Module.Name "Controls" get_controller_module :: Program.Program -> Module.Module get_controller_module p = let Just m = M.lookup moduleName $ Program.modules p in m change_controller_module :: Program.Program -> Controls.Event -> Exc.Exceptional Exception.Message Program.Program change_controller_module p event = case event of EventBool name val -> flip Program.add_module p $ Module.add_rule ( controller_rule name val ) $ get_controller_module p controller_rule :: Show a => Term.Identifier -> a -> Rule.Rule controller_rule name val = Rule.Rule ( read "checkBox" ) [ Term.Node name [], read "deflt" ] ( Term.Node ( read $ show val ) [] ) controller_module :: [(Term.Identifier, Control)] -> Module.Module controller_module controls = let decls = do ( name, CheckBox deflt ) <- controls return $ Module.Rule_Declaration $ controller_rule name deflt m = Module.Module { Module.name = moduleName , Module.imports = [] , Module.source_text = show m , Module.source_location = "/dev/null" , Module.functions = Module.make_functions decls , Module.declarations = decls } in m create :: WX.Frame b -> [(Term.Identifier, Control)] -> (Controls.Event -> IO ()) -> IO () create frame controls sink = do void $ WXCMZ.windowDestroyChildren frame panel <- WX.panel frame [] ws <- forM controls $ \ ( name, con ) -> case con of CheckBox val -> do cb <- WX.checkBox panel [ text := Term.name name , checked := val ] set cb [ on command := do c <- get cb checked sink $ EventBool name c ] return $ widget cb set frame [ layout := container panel $ row 5 ws ] collect :: Program.Program -> [ ( Term.Identifier, Control ) ] collect p = do ( _mod, contents ) <- M.toList $ Program.modules p Module.Rule_Declaration rule <- Module.declarations contents ( _pos, term ) <- Term.subterms $ Rule.rhs rule case Term.viewNode term of Just ( "checkBox" , [ Term.Node tag [], Term.Node val [] ] ) -> return ( tag , CheckBox $ read ( Term.name val ) ) _ -> []