testProg = Main
{ initialState = 1
, initialRequests = [GfxText red (pt 0 0) "foo", GfxText blue (pt 100 100) "bar"]
- , eventHandler = \s e -> (s+1,[GfxText green (pt 50 50) $ show (s,e)])
+ , eventHandler = \s e -> (s+1,[GfxText green (pt 50 (50 + 10 * s)) $ show (s,e)])
, windowWidth = 200
, windowHeight = 200
}
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 { .. }
+ -- Register events
+ Gtk.on window Gtk.exposeEvent $ onExpose buffer
+ Gtk.on window Gtk.configureEvent $ onResize buffer
+ Gtk.on window Gtk.keyPressEvent $ onKeyDown state
+
-- Process any initial requests
processPostponed state
-- 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.
+-- | Called when a key is pressed.
+onKeyDown :: IState -> EventM.EventM EventM.EKey Bool
+onKeyDown s = do
+ keyval <- EventM.eventKeyVal
+ case Gtk.keyToChar keyval of
+ Just c -> liftIO $ post s (KeyIn c)
+ Nothing -> return ()
+ return True -- No clue what this means
+
+-- | Called when (part of) the window should be redrawn. 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
Cairo.paint
return True -- No clue what this means
+-- | Called when the window is resized. Resize the given buffer if needed.
+onResize :: IORef Cairo.Surface -> EventM.EventM EventM.EConfigure Bool
+onResize buffer = do
+ -- Get the current buffer and see if it's still big enough
+ current_buffer <- liftIO $ readIORef buffer
+ sw <- Cairo.imageSurfaceGetWidth current_buffer
+ sh <- Cairo.imageSurfaceGetHeight current_buffer
+ -- Get the current drawwindow and its size
+ dw <- EventM.eventWindow
+ (w, h) <- liftIO $ Gtk.drawableGetSize dw
+ when (w > sw || h > sh) $ liftIO $ do
+ -- Buffer is too small, expand it.
+ new_buffer <- Cairo.createImageSurface Cairo.FormatARGB32 w h
+ -- Fill it with white and copy the old buffer
+ Cairo.renderWith new_buffer $ do
+ Cairo.setSourceRGB 1 1 1
+ Cairo.paint
+ Cairo.setSourceSurface current_buffer 0 0
+ Cairo.paint
+ -- Clean up the old buffer
+ Cairo.surfaceFinish current_buffer
+ -- Store and return the new buffer
+ writeIORef buffer new_buffer
+ return True -- No clue what this means
+
+
{-
runGUI s IS {..} = do
sFrame <- frame
-}
+-- | Handlers for various requests.
+miscHandler, winHandler, gfxHandler :: IState -> Request -> Maybe (IO ())
{-
miscHandler s@IS {..} (FRead fn ) = Just $ readFile fn >>= post s . FileContents fn
miscHandler IS {..} (FWrite fn cnts) = Just $ writeFile fn cnts
-}
winHandler _ _ = Nothing
-gfxHandler s req = case gfxHandler' s req of
+gfxHandler s req = case gfxHandler' req of
Nothing -> Nothing
Just render -> Just $ do
buf <- readIORef (buffer s)
gfxHandler IS {..} (GfxFont st sz) = Just $ buffer `set` [ fontSize := sz, fontFace := st ]
gfxHandler IS {..} (GfxPicture fd pt) = Just $ bitmapCreateFromFile fd >>= \bm -> drawBitmap buffer bm pt False [] >> bitmapGetSize bm >>= dirtyRect' sPanel pt
-}
-gfxHandler' IS {..} (GfxText col (Point x y) st) = Just $ do
+-- | Helper function for gfxHanlder
+gfxHandler' :: Request -> Maybe (Cairo.Render ())
+gfxHandler' (GfxText col (Point x y) st) = Just $ do
+ -- Set the source color, move to the requested position and draw the
+ -- text
setSourceColor col
Cairo.moveTo (fromIntegral x) (fromIntegral y)
Cairo.showText st
-gfxHandler' IS {..} GfxClear = Just $ Cairo.setSourceRGB 1 1 1 >> Cairo.paint
-gfxHandler' _ _ = Nothing
+gfxHandler' GfxClear = Just $ do
+ -- Set the source to white and paint the entire surface with it
+ Cairo.setSourceRGB 1 1 1
+ Cairo.paint
+gfxHandler' _ = Nothing
-- | Sets the source to a pattern fill of the given color
setSourceColor :: Color -> Cairo.Render ()