summaryrefslogtreecommitdiff
path: root/GLWidget.hs
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-04-17 14:18:12 -0400
committerJoe Crayne <joe@jerkface.net>2019-04-17 18:36:53 -0400
commit64f1a100fc887fb2a8bc87e2ac6975e872010ef5 (patch)
tree71e96856bf8a0ebcd14f7ab87124184cb15d868b /GLWidget.hs
parent3899b660b11bf1d3179965ac92a039b8d449306f (diff)
Refactored spinning-logo demo.
Diffstat (limited to 'GLWidget.hs')
-rw-r--r--GLWidget.hs100
1 files changed, 100 insertions, 0 deletions
diff --git a/GLWidget.hs b/GLWidget.hs
new file mode 100644
index 0000000..8a9d23e
--- /dev/null
+++ b/GLWidget.hs
@@ -0,0 +1,100 @@
1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedLabels #-}
3{-# LANGUAGE OverloadedStrings #-}
4module GLWidget where
5
6import Control.Concurrent
7import Data.Functor.Contravariant
8import Data.Int
9import Data.IORef
10import qualified Data.Text as Text
11 ;import Data.Text (Text)
12import Foreign.ForeignPtr
13import Foreign.Ptr
14import GI.Gdk.Objects (GLContext(..),windowCreateGlContext)
15import qualified GI.Gtk as Gtk
16 ;import GI.Gtk as Gtk hiding (main)
17import System.IO
18
19data WidgetMethods st = WidgetMethods
20 { glUnrealize :: st -> IO ()
21 , glRealize :: st -> IO ()
22 , glResize :: st -> Int32 -> Int32 -> IO ()
23 , glRender :: st -> GLContext -> IO Bool
24 , glCreateContext :: st -> IO (Maybe GLContext)
25 , glTitle :: Text
26 }
27
28instance Contravariant WidgetMethods where
29 contramap f w = w
30 { glUnrealize = glUnrealize w . f
31 , glRealize = glRealize w . f
32 , glResize = glResize w . f
33 , glRender = glRender w . f
34 , glCreateContext = glCreateContext w . f
35 }
36
37glmethods :: WidgetMethods GLArea
38glmethods = WidgetMethods
39 { glUnrealize = \_ -> return ()
40 , glRealize = \_ -> return ()
41 , glRender = \_ gl -> return True
42 , glResize = \_ w h -> return ()
43 , glCreateContext =
44 \st -> widgetGetWindow (st::GLArea)
45 >>= maybe (return Nothing)
46 (fmap Just . windowCreateGlContext)
47 , glTitle = "GL Area"
48 }
49
50newGLWidget :: (GLArea -> IO st) -> WidgetMethods st -> IO st
51newGLWidget mk w = do
52 g <- gLAreaNew
53 st <- mk g
54 _ <- on g #render $ glRender w st
55 _ <- on g #resize $ glResize w st
56 _ <- on g #realize $ withCurrentGL g (glRealize w st)
57 _ <- on g #unrealize $ glUnrealize w st
58 _ <- on g #createContext $ nullableContext (glCreateContext w st)
59 return st
60
61withCurrentGL :: GLArea -> IO () -> IO ()
62withCurrentGL glarea action = do
63 gLAreaMakeCurrent glarea
64 e <- gLAreaGetError glarea
65 maybe action oopsG e
66
67nullableContext :: IO (Maybe GLContext) -> IO GLContext
68nullableContext mk = mk >>= maybe mknull return
69 where
70 mknull = do
71 oops "createContext: GLArea has no window."
72 fp <- newForeignPtr_ nullPtr
73 disown <- newIORef Nothing
74 return $ GLContext $ ManagedPtr fp disown
75
76oopsG :: GError -> IO ()
77oopsG e = do
78 msg <- gerrorMessage e
79 oops (Text.unpack msg)
80
81oops :: String -> IO ()
82oops s = hPutStrLn stderr s
83
84runGLApp mk methods = do
85 _ <- Gtk.init Nothing
86
87 let mkChild = newGLWidget mk methods
88
89 window <- do
90 w <- windowNew WindowTypeToplevel
91 windowSetDefaultSize w 760 760
92 windowSetTitle w (glTitle methods)
93 containerSetBorderWidth w 0
94 _ <- on w #deleteEvent $ \_ -> mainQuit >> return True
95 child <- mkChild
96 containerAdd w child
97 return w
98
99 widgetShowAll window
100 Gtk.main