packages feed

apelsin-1.0: src/ServerBrowser.hs

module ServerBrowser where
import Graphics.UI.Gtk
import Control.Concurrent.STM
import Data.IORef
import qualified Data.ByteString.Char8 as B
import Data.Ord
import Network.Tremulous.Protocol
import Text.Printf

import Types
import GtkUtils
import FilterBar
import InfoBox
import TremFormatting
import Constants
import Config

newServerBrowser :: Bundle -> (Bool -> GameServer -> IO ()) -> IO (VBox, IO ())
newServerBrowser Bundle{..} setServer = do
	Config {colors} <- atomically $ readTMVar mconfig
	rawmodel	<- listStoreNew []
	filtered	<- treeModelFilterNew rawmodel []
	model		<- treeModelSortNewWithModel filtered	
	view		<- treeViewNewWithModel model
	
	addColumnsFilterSort rawmodel filtered model view (Just (comparing gameping)) [
		  ("_Game"	, 0	, False	, False	, False	, showGame , Just (comparing (\x -> (protocol x, gamemod x))))
		, ("_Name"	, 0	, True	, True	, True	, pangoPretty colors . hostname	, Just (comparing hostname))
		, ("_Map"	, 0	, True	, False	, False	, take 16 . unpackorig . mapname	, Just (comparing mapname))
		, ("P_ing"	, 1	, False	, False , False	, show . gameping	, Just (comparing gameping))
		, ("_Players"	, 1	, False	, False , False	, showPlayers		, Just (comparing nplayers))
		]

	(infobox, statNow, statTot, statRequested) <- newInfoboxBrowser
	
	Config {filterBrowser, filterEmpty} <- atomically $ readTMVar mconfig
	(filterbar, current) <- newFilterBar filtered statNow filterBrowser
	empty <- checkButtonNewWithMnemonic "_empty"
	set empty [ toggleButtonActive := filterEmpty ]
	boxPackStart filterbar empty PackNatural 0
	on empty toggled $ do
		treeModelFilterRefilter filtered
		n <- treeModelIterNChildren filtered Nothing
		set statNow [ labelText := show n ]


	treeModelFilterSetVisibleFunc filtered $ \iter -> do
		GameServer{..}	<- treeModelGetRow rawmodel iter
		s		<- readIORef current
		showEmpty	<- toggleButtonGetActive empty
		return $ (showEmpty || not (null players)) && (B.null s ||
			smartFilter s [
				  cleanedCase hostname
				, cleanedCase mapname
				, proto2string protocol
				, maybe "" cleanedCase gamemod
				])
			
	onCursorChanged view $ do
		(x, _)		<- treeViewGetCursor view
		Just vIter	<- treeModelGetIter model x
		sIter		<- treeModelSortConvertIterToChildIter model vIter
		fIter		<- treeModelFilterConvertIterToChildIter filtered sIter
		gameserver	<- treeModelGetRow rawmodel fIter
		setServer False gameserver

	onRowActivated view $ \path _ -> do
		Just vIter	<- treeModelGetIter model path
		sIter		<- treeModelSortConvertIterToChildIter model vIter
		fIter		<- treeModelFilterConvertIterToChildIter filtered sIter
		gameserver	<- treeModelGetRow rawmodel fIter
		setServer True gameserver
		
	
	scrollview <- scrolledWindowNew Nothing Nothing
	scrolledWindowSetPolicy scrollview PolicyNever PolicyAlways
	containerAdd scrollview view
	
	let updateF = do
		PollResult{..} <- atomically $ readTMVar mpolled
		listStoreClear rawmodel
		treeViewColumnsAutosize view
		mapM_ (listStoreAppend rawmodel) polled
		treeModelFilterRefilter filtered
		set statTot		[ labelText := show serversResponded ]
		set statRequested	[ labelText := show (serversRequested-serversResponded) ]
		n <- treeModelIterNChildren filtered Nothing
		set statNow [ labelText := show n ]
		
	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{..} = proto2string protocol ++ maybe "" (("-"++) . htmlEscape . unpackorig) gamemod
	showPlayers GameServer{..} = printf "%d / %2d" nplayers slots