module NClient.GUI (gui) where import Control.Applicative ((<$>)) import Control.Concurrent (forkIO, threadDelay) import Control.Concurrent.Chan (readChan, writeChan) import Control.Monad (forever, forM_, void) import Data.IORef (newIORef, atomicModifyIORef) import Graphics.Vty import Graphics.Vty.Widgets.All import NClient.Connect import NClient.Message.Format import qualified NClient.Message.History as H import qualified NClient.Message.Split as S gui :: (Input, Output) -> IO () gui (i,o) = do history <- newIORef $ H.empty 10 messages <- newList (getNormalAttr defaultContext) newMessage <- editWidget box <- vBox messages newMessage ui <- centered box fg <- newFocusGroup void $ addToFocusGroup fg newMessage c <- newCollection void $ addToCollection c ui fg -- Send message to server newMessage `onActivate` \this -> getEditText this >>= toC2S >>= writeChan o -- -- Add send message to history newMessage `onActivate` \this -> getEditText this >>= \t -> atomicModifyIORef history (\h -> let a = H.prepend t h in (a, H.line a)) >>= setEditText this -- -- Catch history movements newMessage `onKeyPressed` \this k m -> case (k,m) of (KUp, []) -> do t <- getEditText this t' <- atomicModifyIORef history $ \h -> let h' = H.next t h in (h', H.line h') setEditText this t' return True (KDown, []) -> do t' <- atomicModifyIORef history $ \h -> let h' = H.previous h in (h', H.line h') setEditText this t' return True _ -> return False -- -- Read server messages when they come void . forkIO . forever $ readChan i >>= \m -> do let addMessage f xs ys = textWidget f xs >>= addToList ys xs >> scrollDown ys schedule $ do a:as <- S.words (fromS2C m) . region_width <$> getCurrentSize messages addMessage (formatter Tail m) a messages forM_ as $ \g -> addMessage (formatter Full m) g messages threadDelay 10000 -- runUi c defaultContext