macbeth-lib-0.0.12: src/Macbeth/Wx/ToolBox.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase #-}
module Macbeth.Wx.ToolBox (
wxToolBox
) where
import Macbeth.Fics.FicsMessage
import Macbeth.Fics.Api.Player
import Macbeth.Wx.Configuration
import Macbeth.Wx.Finger
import Macbeth.Wx.GamesList
import Macbeth.Wx.Login
import Macbeth.Wx.Match
import Macbeth.Wx.Seek
import Macbeth.Wx.Utils
import Macbeth.Wx.PlayersList
import Macbeth.Wx.SoughtList
import Macbeth.Wx.Game
import Macbeth.Wx.Challenge
import Macbeth.Wx.PartnerOffer
import Macbeth.Wx.Pending
import Paths
import Control.Concurrent
import Control.Concurrent.Chan ()
import Control.Monad
import Foreign.Marshal.Alloc
import Foreign.Storable
import Foreign.Ptr
import Foreign.C.Types
import Graphics.UI.WX hiding (when)
import Graphics.UI.WXCore hiding (when)
import System.FilePath
import System.IO
import System.IO.Unsafe
eventId = wxID_HIGHEST + 1
wxToolBox :: Handle -> Chan FicsMessage -> IO ()
wxToolBox h chan = do
f <- frame [ text := "Macbeth"]
tbar <- toolBarEx f False False []
tbarItem_seek <- toolItem tbar "Seek" False (unsafePerformIO $ getDataFileName $ "icons" </> "bullhorn.gif")
[ on command := dupChan chan >>= wxSeek h False, enabled := False, tooltip := "Seek" ]
tbarItem_match <- toolItem tbar "Match" False (unsafePerformIO $ getDataFileName $ "icons" </> "dot-circle-o.gif")
[ on command := dupChan chan >>= wxMatch h False, enabled := False, tooltip := "Match" ]
tbarItem_finger <- toolItem tbar "Finger" False (unsafePerformIO $ getDataFileName $ "icons" </> "fa-question.gif")
[ on command := hPutStrLn h "4 finger", enabled := False, tooltip := "Finger"]
status <- statusField []
statusLag <- statusField [ statusWidth := 100 ]
_ <- timer f [ interval := 2 * 60 * 1000, on command := hPutStrLn h "4 ping"]
statusLoggedIn <- statusField [ statusWidth := 100]
nb <- notebook f []
-- Sought list
slp <- panel nb []
(sl, soughtListHandler) <- wxSoughtList slp h
-- Games list
glp <- panel nb []
(gl, gamesListHandler) <- wxGamesList glp h
-- Pending
pending <- panel nb []
(pendingWidget, pendingHandler) <- wxPending h pending
-- Players
players <- panel nb []
(playersWidget, playersHandler) <- wxPlayersList players h
-- Console
cp <- panel nb []
ct <- textCtrlEx cp (wxTE_MULTILINE .+. wxTE_RICH .+. wxTE_READONLY) [font := fontFixed]
ce <- entry cp []
set ce [on enterKey := emitCommand ce h]
-- menu
m_file <- menuPane [text := "&File"]
menuItem m_file [text := "Settings", on command := dupChan chan >>= wxConfiguration ]
set f [ statusBar := [status, statusLoggedIn, statusLag],
layout := tabs nb
[ tab "Sought" $ container slp $ fill $ widget sl
, tab "Games" $ container glp $ fill $ widget gl
, tab "Pending" $ container pending $ fill $ widget pendingWidget
, tab "Players" $ container players $ fill $ widget playersWidget
, tab "Console" $ container cp ( column 5 [ fill $ widget ct
, hfill $ widget ce])
]
, menuBar := [m_file]
, outerSize := sz 600 600
]
-- preselect first tab
notebookSetSelection nb 0
vCmd <- newEmptyMVar
threadId <- forkIO $ eventLoop eventId chan vCmd f
windowOnDestroy f $ writeChan chan WxClose >> killThread threadId
evtHandlerOnMenuCommand f eventId $ takeMVar vCmd >>= \cmd ->
gamesListHandler cmd >>
soughtListHandler cmd >>
pendingHandler cmd >>
playersHandler cmd >>
case cmd of
NoSuchGame -> do
set status [text := "No such game. Updating games..."]
hPutStrLn h "4 games"
UserNotLoggedIn username -> do
set status [text := username ++ " is not logged in."]
hPutStrLn h "4 who"
PartnerNotOpen userHandle -> set status [text := name userHandle ++ " is not open for bughouse."]
PartnerOffer userHandle -> dupChan chan >>= wxPartnerOffer h userHandle
PartnerAccepted userHandle -> set status [text := name userHandle ++ " agrees to be your partner."]
PartnerDeclined userHandle -> set status [text := name userHandle ++ " declines the partnership request."]
SeekNotAvailable -> set status [text := "That seek is not available."]
InvalidPassword -> void $ set status [text := "Invalid password."]
LoginTimeout -> set status [ text := "Login Timeout." ]
Login -> dupChan chan >>= wxLogin h
LoggedIn handle -> do
set nb [on click := (onMouse nb >=> clickHandler h nb)]
hPutStrLn h `mapM_` [ "ping", "set seek 0", "set style 12", "iset pendinfo 1", "iset seekinfo 1", "iset nowrap 1", "iset defprompt 1", "iset block 1", "2 iset lock 1"]
set statusLoggedIn [ text := name handle]
mapM_ (`set` [ enabled := True ]) [tbarItem_seek, tbarItem_match, tbarItem_finger]
GuestLogin _ -> do
set tbarItem_seek [on command := dupChan chan >>= wxSeek h True ]
set tbarItem_match [on command := dupChan chan >>= wxMatch h True ]
msg@(Finger {}) -> dupChan chan >>= wxInfo msg
msg@(History {}) -> dupChan chan >>= wxInfo msg
WxObserve move chan' -> wxGame h move chan'
MatchRequested c -> dupChan chan >>= wxChallenge h c
WxMatchAccepted move chan' -> wxGame h move chan'
MatchDeclined user -> set status [text := user ++ " declines the match offer."]
MatchUserNotLoggedIn user -> set status [text := user ++ " not logged in."]
Ping _ avg _ -> set statusLag [ text := "Lag: " ++ show avg ++ "ms"]
TextMessage text -> appendText ct text
_ -> return ()
emitCommand :: TextCtrl () -> Handle -> IO ()
emitCommand textCtrl h = get textCtrl text >>= hPutStrLn h . ("5 " ++) >> set textCtrl [text := ""]
onMouse :: Notebook() -> Point -> IO Int
onMouse nb p = propagateEvent >> notebookHitTest nb p flag
clickHandler :: Handle -> Notebook () -> Int -> IO ()
clickHandler h nb idx = notebookGetPageText nb idx >>= \case
"Games" -> hPutStrLn h "5 games"
"Players" -> hPutStrLn h "5 who"
_ -> return ()
{-# NOINLINE flag #-}
flag :: Ptr CInt
flag = unsafePerformIO flag'
where flag' = do
work <- malloc::IO (Ptr CInt)
poke work (fromIntegral wxBK_HITTEST_ONPAGE)
return work