{----------------------------------------------------------------------------- reactive-banana-threepenny Example: Two Counters. ------------------------------------------------------------------------------} {-# LANGUAGE ScopedTypeVariables #-} -- allows "forall t. Moment t" import qualified Graphics.UI.Threepenny as UI import Graphics.UI.Threepenny.Core hiding (Event) import Reactive.Banana import Reactive.Banana.Threepenny {----------------------------------------------------------------------------- Main ------------------------------------------------------------------------------} main :: IO () main = do startGUI Config { tpPort = 10000 , tpCustomHTML = Nothing , tpStatic = "" } setup setup :: Window -> IO () setup window = do return window # set title "Two Counters" bup <- UI.button #+ [string "Up" ] bdown <- UI.button #+ [string "Down"] bswitch <- UI.button #+ [string "Switch Counters"] out1 <- UI.span out2 <- UI.span getBody window #+ [ column [row [element bup, element bdown, element bswitch] ,grid [[string "First Counter:", element out1] ,[string "Second Counter:", element out2]]]] let networkDescription :: forall t. Frameworks t => Moment t () networkDescription = do eup <- event UI.click bup edown <- event UI.click bdown eswitch <- event UI.click bswitch let -- do we act on the left button? firstcounter :: Behavior t Bool firstcounter = accumB True $ not <$ eswitch -- joined state of the two counters counters :: Behavior t (Int, Int) counters = accumB (0,0) $ union ((increment <$> firstcounter) `apply` eup) ((decrement <$> firstcounter) `apply` edown) increment left _ (x,y) = if left then (x+1,y) else (x,y+1) decrement left _ (x,y) = if left then (x-1,y) else (x,y-1) return out1 # sink text (show . fst <$> counters) return out2 # sink text (show . snd <$> counters) network <- compile networkDescription actuate network