-- | -- Maintainer: Oliver Mielentz, Henning Guenther -- -- A module assembling the single gui modules to one user interface. module Barracuda.GUI ( guiNew ) where import Data.IORef import Graphics.UI.Gtk import Graphics.UI.Gtk.ModelView as New import Barracuda.GUI.CertificateLoader import Barracuda.GUI.ChannelCreator import Barracuda.GUI.ChannelList import Barracuda.GUI.ChannelManager import Barracuda.GUI.DownloadManager import Barracuda.GUI.UserList import Barracuda.GUI.InputField import Barracuda.GUI.ChatView import Data.List as List import Data.Map as Map import Data.Set as Set import Data.Time.Clock import Control.Concurrent import Control.Concurrent.Chan import Control.Concurrent.MVar import Barracuda.GUI.ServerInterface import Network.AdHoc.Channel import Network.AdHoc.UserID import Network.AdHoc.Message import Network.GnuTLS.X509 import System.Environment import Data.ByteString (pack) import Data.ByteString.Char8 (unpack) -- | Spawns a new user interface. guiNew :: GUI guiNew send = do precv <- newIORef (const $ return ()) win <- windowNew windowSetDefaultSize win 340 300 cl <- loaderNew (\cert key -> case certificateGetUserID cert of Nothing -> error "Think of something here" Just name -> do f <- guiNew' name send writeIORef precv f send (SetUser name cert key) widgetDestroy win ) win `containerAdd` (loaderGetWidget cl) widgetShowAll win return (\msg -> do f <- readIORef precv f msg) guiNew' :: UserID -> GUI guiNew' user send = do win <- windowNew let goldenRatio = (1 + sqrt (5 :: Double)) / (fromInteger 2) let height = 500 windowSetDefaultSize win (round (goldenRatio * (fromInteger.toInteger) height)) height win `windowSetTitle` ("Barracuda - "++show user) manager <- channelManagerNew (\attach -> do dm <- downloadManagerNew attach win <- windowNew win `containerAdd` (downloadManagerGetWidget dm) widgetShowAll win) (\cname cid user -> send (Authorize user cname cid)) user >>= newMVar -- generates the UserList Widget userList <- frameNew userl <- userListNew userlabel <- labelNew (Just "Users in active Channel") labelSetUseMarkup userlabel True frameSetLabelWidget userList userlabel userList `containerAdd` (userListGetWidget userl) -- generates the ChannelList Widget channel <- channelListNew channelList <- frameNew channellabel <- labelNew (Just "Channels") labelSetUseMarkup channellabel True frameSetLabelWidget channelList channellabel channelList `containerAdd` (channelListGetWidget channel) -- generates the InputField input <- inputFieldNew input `onSend` (\txt attach -> do cm <- readMVar manager case channelManagerChannel cm of Just (cname,cid,True) -> send (SendMsg cname cid txt attach) _ -> return () inputFieldClear input) -- place the widgets hPan <- hPanedNew vbox <- vBoxNew False 0 vPan_lists <- vPanedNew hPan `containerAdd` vPan_lists hPan `containerAdd` vbox chatviewframe <- frameNew chatviewlabel <- labelNew (Just "Chat") let changeMainWidget wid = do child <- binGetChild chatviewframe case child of Nothing -> return () Just rchild -> containerRemove chatviewframe rchild containerAdd chatviewframe wid widgetShowAll chatviewframe let update cm = channelManagerCheckState cm changeMainWidget let updateUserList cm = userListSetUsers userl (channelManagerUsers cm) channel `onChannelSelect` (\chan -> modifyMVar_ manager (\cm -> do let ncm = channelManagerSelect (channelName chan) (channelID chan) cm nncm <- channelManagerCheckState ncm changeMainWidget updateUserList nncm chatViewScroll $ view nncm return nncm)) channel `onChannelJoin` (\chan -> send (WantJoin (channelName chan) (channelID chan))) channel `onChannelLeave` (\chan -> send (WantLeave (channelName chan) (channelID chan))) channel `onChannelCreate` (do dialog <- windowNew windowSetTitle dialog "Create new channel" creat <- channelCreatorNew dialog `set` [windowTransientFor:=win ,windowModal:=True ,windowAllowGrow:=False] dialog `containerAdd` (channelCreatorGetWidget creat) creat `channelCreatorOnEnter` (\name descr priv -> do send (CreateChannel (mkChannelName name) descr (if priv then Just (Set.empty) else Nothing)) widgetDestroy dialog) widgetShowAll dialog ) labelSetUseMarkup chatviewlabel True frameSetLabelWidget chatviewframe chatviewlabel boxPackStart vbox chatviewframe PackGrow 0 boxPackStart vbox (inputFieldGetWidget input) PackNatural 0 set vPan_lists [ containerChild := frame | frame <- [ channelList, userList ] ] vPan_lists `set` [panedPosition := 300] win `containerAdd` hPan withMVar manager update win `onDestroy` (do send CMClose modifyMVar_ manager (return.channelManagerNoState) ) widgetShowAll win let receive msg = postGUIAsync $ case msg of AllChans mp -> do modifyMVar_ manager $ \cm -> update $ channelManagerUpdate mp cm cm <- readMVar manager channelListSetChannels channel (List.map (\((cname,cid),(desc,priv,users)) -> Chan (show cname ++ (case desc of "" -> "" _ -> " (" ++ desc ++ ")")) cname cid priv (Set.member (channelManagerUsername cm) users)) (Map.assocs mp)) (fmap (\(cname,cid,_)-> (cname,cid)) $ channelManagerChannel cm) updateUserList cm Receive cname cid sender msg attach time delayed -> modifyMVar_ manager $ channelManagerPost cname cid time sender msg attach delayed WantsAuth user cname cid -> do time <- getCurrentTime modifyMVar_ manager $ channelManagerWantsAuth cname cid time user ErrGeneral level title str -> do dia <- messageDialogNew (Just win) [] level ButtonsOk str windowSetTitle dia title dialogRun dia widgetDestroy dia ErrNotDelivered user cname cid msg _ time -> modifyMVar_ manager $ channelManagerError cname cid time ((constructAnd $ fmap show user) ++ " didn't get your message.") _ -> print msg return receive constructAnd :: [String] -> String constructAnd = constructAnd' "" where constructAnd' :: String -> [String] -> String constructAnd' str [] = str constructAnd' str (x:xs) | List.null str = constructAnd' x xs | List.null xs = str++" and "++x | otherwise = constructAnd' (str++", "++x) xs