<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
<title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
Michael Mossey wrote:<br>
<blockquote cite="mid:4AA96C0F.6070302@alumni.caltech.edu" type="cite">Duncan
Coutts wrote:
<br>
<blockquote type="cite">On Wed, 2009-09-09 at 18:29 -0700, Michael P
Mossey wrote:
<br>
<blockquote type="cite">I'm trying to learn qtHaskell. I realize
few people on this list know anything about qtHaskell, but I have a
question that probably relates to all GUIs as implemented in Haskell. I
just need a hint that could help me figure out the next step, which I
might be able to infer from the qtHaskell API.
<br>
</blockquote>
<br>
Ultimately it's done by some kind of mutable state, either an IORef,
<br>
MVar or a thread.
<br>
</blockquote>
</blockquote>
In wxHaskell, the 'simplest' way to code this looks something like the
following (literate Haskell)<br>
<br>
<span style="font-size: 11pt; font-family: "Calibri","sans-serif";"><span
style="color: rgb(31, 73, 125);"></span></span><tt>Structure
containing 'state' of all of the GUI objects<br>
<br>
> data UIState = UIState { uiConnect :: Button ()<br>
> , uiPort :: TextCtrl ()<br>
> , uiUser :: TextCtrl ()<br>
> , uiPasswd :: TextCtrl ()<br>
> , uiSandbox :: TextCtrl ()<br>
> , uiClients :: ComboBox ()<br>
> , uiChanges :: SingleListBox ()<br>
> , uiChangeInfo :: TextCtrl ()<br>
> , uiOrigin :: TextCtrl ()<br>
> , uiUpdate :: TextCtrl ()<br>
> , uiFrame :: Frame ()<br>
> }<br>
<br>
> uiState = unsafePerformIO $ newMVar (Nothing :: Maybe UIState)<br>
<br>
Ensure that we initialize exactly once...<br>
<br>
> uiInitState bt pt us pw sb cl ci ch or up f =<br>
> takeMVar uiState >>= \st -><br>
> case st of<br>
> Nothing -> let st' = UIState bt pt us pw sb cl ci ch or
up f in<br>
> putMVar uiState (Just st')<br>
> Just _ -> return ()<br>
<br>
Get the mutable state.<br>
Note that in the error case we deliberately do not put the MVar back,
as a means<br>
to block all threads waiting on the MVar (as this would indicate a
general<br>
programming/threading issue to be identified).<br>
<br>
> getMVarState mv txt =<br>
> takeMVar mv >>= \may_st -><br>
> case may_st of<br>
> Nothing -> error (txt ++ " is not available")<br>
> Just st -> putMVar mv may_st >><br>
> return st<br>
<br>
Fetch the UI state - this will fail fatally if we fetch before state is
initialized<br>
<br>
> uiGetState = getMVarState uiState "UI state"</tt><br>
<br>
I don't have anything as neat to show you as Duncan's suggetion (I'd
also be interested to see a cleaner way to do it - this sort of code
always grates a little with me, although all of the major Haskell GUI
bindings seem to need a similar programming style.<br>
<br>
However, at the most basic 'trying it out' level, I suspect that
something very like this will work just as well for qtHaskell as it
does for wxHaskell.<br>
<blockquote cite="mid:4AA96C0F.6070302@alumni.caltech.edu" type="cite">
<blockquote type="cite">On top of these you can layer nicer stuff
like a state monad (with a
<br>
'runState' function that saves and restores from an IORef).
<br>
<br>
A personal favourite of mine is having the GUI event handler post data
<br>
over a channel to a thread. That thread reads from the channel and
deals
<br>
with the events. The state of the GUI app is then held as local
<br>
parameters in that thread.
<br>
<br>
Doing this of course requires that the GUI lib you're using can cope
<br>
with normal Haskell (forkIO) threads. This is possible with gtk2hs, I
<br>
don't know about the others.
<br>
</blockquote>
</blockquote>
Regards<br>
Jeremy<br>
</body>
</html>