apelsin-1.2: src/ServerBrowser.hs
module ServerBrowser (newServerBrowser, browserUpdateOne) where
import Graphics.UI.Gtk
import Data.IORef
import Data.Ord
import Data.Monoid
import Network.Tremulous.Protocol
import qualified Network.Tremulous.StrictMaybe as SM
import Text.Printf
import qualified Data.ByteString.Char8 as B
import Types
import GtkUtils
import GtkExts
import FilterBar
import InfoBox
import TremFormatting
import Constants
import Config
newServerBrowser :: Bundle -> SetCurrent -> IO (VBox, PolledHook)
newServerBrowser bundle@Bundle{..} setServer = do
Config {..} <- readMVar mconfig
gen@(GenFilterSort raw filtered sorted view) <- newGenFilterSort browserStore
addColumnFS gen "_Game" False
(Just (comparing protocol `mappend` comparing gamemod `mappend` comparing gameping))
(rememberColumn bundle 0)
cellRendererTextNew
[]
(\rend -> cellSetText rend . showGame)
addColumnFS gen "_Name" True
(Just (comparing hostname `mappend` comparing gameping))
(rememberColumn bundle 1)
cellRendererTextNew
[cellTextEllipsize := EllipsizeEnd]
(\rend -> cellSetMarkup rend . pangoPrettyBS colors . hostname)
addColumnFS gen "_Map" False
(Just (comparing mapname `mappend` comparing gameping))
(rememberColumn bundle 2)
cellRendererTextNew []
(\rend -> cellSetText rend . SM.maybe "" (B.take 16 . original) . mapname)
addColumnFS gen "P_ing" False
(Just (comparing gameping `mappend` comparing hostname))
(rememberColumn bundle 3)
cellRendererTextNew
[cellXAlign := 1]
(\rend x -> set rend [cellText := show $ gameping x])
addColumnFS gen "_Players" False
(Just (comparing nplayers `mappend` flip (comparing gameping)))
(rememberColumn bundle 4)
cellRendererTextNew
[cellXAlign := 1]
(\rend x -> set rend [cellText := showPlayers x])
treeSortableSetSortColumnId sorted browserSort browserOrder
(infobox, statNow, statTot, statRequested) <- newInfoboxBrowser
(filterbar, current) <- newFilterBar parent filtered statNow filterBrowser
empty <- checkButtonNewWithMnemonic "_empty"
set empty [ toggleButtonActive := filterEmpty ]
boxPackStart filterbar empty PackNatural spacingHalf
on empty toggled $ do
treeModelFilterRefilter filtered
labelSetText statNow . show =<< treeModelIterNChildren filtered Nothing
treeModelFilterSetVisibleFunc filtered $ \iter -> do
GameServer{..} <- treeModelGetRow raw iter
s <- readIORef current
showEmpty <- toggleButtonGetActive empty
return $ (showEmpty || not (null players)) &&
(smartFilter s
[ cleanedCase hostname
, SM.maybe "" cleanedCase mapname
, SM.maybe "" cleanedCase version
, proto2string protocol
, SM.maybe "" cleanedCase gamemod
])
on view cursorChanged $ do
(path, _) <- treeViewGetCursor view
setServer False =<< getElementPath gen path
on view rowActivated $ \path _ ->
setServer True =<< getElementPath gen path
scrollview <- scrolledWindowNew Nothing Nothing
scrolledWindowSetPolicy scrollview PolicyNever PolicyAlways
containerAdd scrollview view
let updateF PollResult{..} = do
listStoreClear raw
treeViewColumnsAutosize view
mapM_ (listStoreAppend raw) polled
labelSetText statTot $ show serversResponded
labelSetText statRequested $ show (serversRequested - serversResponded)
labelSetText statNow . show =<< treeModelIterNChildren filtered Nothing
box <- vBoxNew False 0
boxPackStart box filterbar PackNatural spacing
boxPackStart box scrollview PackGrow 0
boxPackStart box infobox PackNatural 0
return (box, updateF)
where
showGame GameServer{..} = B.concat (proto2string protocol : SM.maybe [] ((\x -> ["-",x]) . original) gamemod)
showPlayers GameServer{..} = printf "%d / %2d" nplayers slots
browserUpdateOne :: BrowserStore -> GameServer -> IO ()
browserUpdateOne raw gs = treeModelForeach raw $ \iter -> do
let i = listStoreIterToIndex iter
e <- listStoreGetValue raw i
if address e == address gs
then listStoreSetValue raw i gs >> return True
else return False
rememberColumn :: Bundle -> Int -> TreeViewColumn -> IO ()
rememberColumn Bundle{..} n col = do
order <- treeViewColumnGetSortOrder col
current <- takeMVar mconfig
let new = current {browserSort = n, browserOrder = order}
putMVar mconfig new
configToFile parent new