gsmenu-1.1: GSMenu/GCCache.hs
-----------------------------------------------------------------------------
-- |
-- Module : GSMenu.GCCache
-- Author : Troels Henriksen <athas@sigkill.dk>
-- License : MIT-style (see LICENSE)
--
-- Stability : stable
-- Portability : unportable
--
-- Cache for creating and retrieving Xlib GC values.
--
-----------------------------------------------------------------------------
module GSMenu.GCCache ( getGC
, GCCache
, empty
, allGCs
, freeCache
, GCParams(..)
) where
import Control.Monad.Trans
import qualified Data.Map as M
import Data.Maybe
import Graphics.X11.Xlib
import GSMenu.Font
import GSMenu.Util
data GCParams = GCParams {
gc_fg :: String
} deriving (Eq, Ord)
type InnerCache = M.Map GCParams GC
newtype GCCache = GCCache (M.Map Drawable InnerCache)
empty :: GCCache
empty = GCCache M.empty
innerCache :: GCCache -> Drawable -> InnerCache
innerCache (GCCache c) d =
fromMaybe M.empty $ M.lookup d c
cachedGC :: GCCache -> Drawable -> GCParams -> Maybe GC
cachedGC cache d p = M.lookup p $ innerCache cache d
setCached :: GCCache -> Drawable -> GCParams -> GC -> GCCache
setCached cache@(GCCache c) d p gc =
GCCache $ M.insert d inner' c
where inner = innerCache cache d
inner' = M.insert p gc inner
getGC :: MonadIO m => Display -> Screen -> GCCache -> Drawable -> GCParams -> m (GC, GCCache)
getGC dpy screen cache d p =
case cachedGC cache d p of
Just x -> return (x, cache)
Nothing -> do
x <- getGC'
return (x, setCached cache d p x)
where getGC' = io $ do
gc <- createGC dpy d
fgc <- initColor dpy $ gc_fg p
case fgc of
Just fgc' -> setForeground dpy gc fgc'
Nothing -> do err $ "Bad color " ++ gc_fg p
setForeground dpy gc wp
return gc
wp = whitePixelOfScreen screen
allGCs :: GCCache -> [GC]
allGCs (GCCache c) = concatMap M.elems $ M.elems c
freeCache :: Display -> GCCache -> IO ()
freeCache dpy = mapM_ (freeGC dpy) . allGCs