X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=FPPrac.hs;h=79a6a0ac9405b167d0c76b931c9292bdc49462c4;hb=ea597e505a69974dfd35dd2728b1e9f3bb109fa9;hp=ddf421ebf8821c191cfb8c2fd85fb5786c9c4b42;hpb=cb9aa250052bfae8f8c34cb74701f0c381ada2c6;p=matthijs%2Fprojects%2Ffpprac.git diff --git a/FPPrac.hs b/FPPrac.hs index ddf421e..79a6a0a 100644 --- a/FPPrac.hs +++ b/FPPrac.hs @@ -9,6 +9,11 @@ module FPPrac ( ) where import qualified Graphics.UI.Gtk as Gtk +import Graphics.UI.Gtk (AttrOp(..)) -- For the := constructor +import qualified Graphics.Rendering.Cairo as Cairo +import qualified Graphics.UI.Gtk.Gdk.EventM as EventM + +import Control.Monad.Trans -- for liftIO import Data.IORef import Control.Applicative import Control.Monad @@ -93,10 +98,9 @@ testProg = Main } data IState = forall s. IS - { {-sFrame :: Frame () - , sPanel :: Panel () - , buffer :: MemoryDC () - , -}postponed :: IORef [Request] + { window :: Gtk.Window + , buffer :: IORef Cairo.Surface + , postponed :: IORef [Request] , usrState :: IORef s , usrProg :: TinaStep s } @@ -129,11 +133,55 @@ runTina :: TinaProgram -> IO () runTina Main {..} = do usrState <- newIORef initialState postponed <- newIORef (GfxText (rgb 0 0 0) (pt 50 50) "foo" : GfxClear :initialRequests) - let state = IS { usrProg = eventHandler, .. } - runGUI {-(sz windowWidth windowHeight) -}state + let state = IS { window = undefined, buffer = undefined, usrProg = eventHandler, .. } + runGUI windowWidth windowHeight state + +runGUI :: Int -> Int -> IState -> IO () +runGUI w h (IS { .. }) = do + -- Init GTK. + Gtk.initGUI + + -- Create a window, which will make the mainloop terminated when + -- it is closed. + window <- Gtk.windowNew + + Gtk.set window [ Gtk.containerBorderWidth := 10 + , Gtk.windowTitle := "FP Practicum" + , Gtk.windowDefaultWidth := w + , Gtk.windowDefaultHeight := h + ] + Gtk.onDestroy window Gtk.mainQuit + + -- Create a buffer to draw on (name the actual buffer buffer', so we + -- can use IS { .. } syntax below to pack the state. Using a record update + -- wouldn't work, probably because Cairo.Surface contains an existential + -- type... + -- We put the buffer in an IORef, so we can change it for a new one + -- later on (on window resizes). + buffer' <- Cairo.createImageSurface Cairo.FormatARGB32 w h + buffer <- newIORef buffer' + + -- Register the expose event + Gtk.on window Gtk.exposeEvent $ onExpose buffer + + -- Repack state + let state = IS { .. } + + -- Show the window and start the Gtk mainloop. + Gtk.widgetShowAll window + Gtk.mainGUI + +-- | Copy the given surface to the exposed window on an expose event. +onExpose :: IORef Cairo.Surface -> EventM.EventM EventM.EExpose Bool +onExpose buffer = do + current_buffer <- liftIO $ readIORef buffer + dw <- EventM.eventWindow + -- Copy the buffer to the window + liftIO $ Gtk.renderWithDrawable dw $ do + Cairo.setSourceSurface current_buffer 0 0 + Cairo.paint + return True -- No clue what this means -runGUI :: {-Size ->-} IState -> IO () -runGUI s = do return () {- runGUI s IS {..} = do sFrame <- frame