-
Notifications
You must be signed in to change notification settings - Fork 30
/
Main.hs
154 lines (106 loc) · 4.36 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
module Main where
import Data.IORef
import Graphics.Gloss.Interface.IO.Game
import Buttons
import CallbackSystem
import GlossInterface
main :: IO ()
main = do
-- Mutable count
count0 <- newIORef 0
count5 <- newIORef 0
count10 <- newIORef 0
mode0 <- newIORef True
mode5 <- newIORef True
mode10 <- newIORef True
-- Places where callbacks can be registered
onClick0 <- newHook
onClick5 <- newHook
onClick10 <- newHook
onToggle0 <- newHook
onToggle5 <- newHook
onToggle10 <- newHook
-- Delegate to a helper function, to help with scoping
go count0 mode0 onClick0 onToggle0
count5 mode5 onClick5 onToggle5
count10 mode10 onClick10 onToggle10
where
go :: IORef Int -> IORef Bool -> Hook () -> Hook ()
-> IORef Int -> IORef Bool -> Hook () -> Hook ()
-> IORef Int -> IORef Bool -> Hook () -> Hook ()
-> IO ()
go count0 mode0 onClick0 onToggle0
count5 mode5 onClick5 onToggle5
count10 mode10 onClick10 onToggle10 = do
-- Initial callback network
registerCallback onClick0 clickHandler0
registerCallback onClick5 clickHandler5
registerCallback onClick10 clickHandler10
registerCallback onToggle0 toggleHandler0
registerCallback onToggle5 toggleHandler5
registerCallback onToggle10 toggleHandler10
-- Gloss event loop
eventHook <- newHook
pictureRef <- newIORef =<< render
registerCallback eventHook $ \e -> do
processEvent (filter0 e) onClick0 onToggle0
processEvent (filter5 e) onClick5 onToggle5
processEvent (filter10 e) onClick10 onToggle10
writeIORef pictureRef =<< render
playHook (InWindow "Callback Example" (320, 240) (800, 200))
white
30
pictureRef
eventHook
where
-- Input
processEvent :: Maybe ButtonClick -> Hook () -> Hook () -> IO ()
processEvent (Just Click) onClick _ = triggerCallbacks onClick ()
processEvent (Just Toggle) _ onToggle = triggerCallbacks onToggle ()
processEvent Nothing _ _ = return ()
-- Behaviour
clickHandler0, clickHandler5, clickHandler10 :: Callback ()
clickHandler0 () = modifyIORef count0 (+1)
clickHandler5 () = modifyIORef count5 (+1)
clickHandler10 () = modifyIORef count10 (+1)
toggleHandler0, toggleHandler5, toggleHandler10 :: Callback ()
toggleHandler0 = toggleOff0
toggleHandler5 = toggleOff5
toggleHandler10 () = modifyIORef mode10 not
toggleOff0 :: Callback ()
toggleOff0 () = do
writeIORef mode0 False
writeIORef count0 0
unregisterCallbacks onClick0
unregisterCallbacks onToggle0
registerCallback onToggle0 toggleOn0
toggleOn0 :: Callback ()
toggleOn0 () = do
writeIORef mode0 True
registerCallback onClick0 clickHandler0
unregisterCallbacks onToggle0
registerCallback onToggle0 toggleOff0
toggleOff5 :: Callback ()
toggleOff5 () = do
writeIORef mode5 False
unregisterCallbacks onClick5
unregisterCallbacks onToggle5
registerCallback onToggle5 toggleOn5
toggleOn5 :: Callback ()
toggleOn5 () = do
writeIORef mode5 True
registerCallback onClick5 clickHandler5
unregisterCallbacks onToggle5
registerCallback onToggle5 toggleOff5
-- Output
chooseLabel :: IORef Int -> IORef Bool -> IO Int
chooseLabel countRef modeRef = do
mode <- readIORef modeRef
if mode
then readIORef countRef
else return (-1)
render :: IO Picture
render = renderButtons
<$> chooseLabel count0 mode0 <*> pure Nothing
<*> chooseLabel count5 mode5 <*> pure Nothing
<*> chooseLabel count10 mode10 <*> pure Nothing