-----------------------------------------------------------------------------
-- |
-- Module : XMonadContrib.Tabbed
-- Copyright : (c) David Roundy
-- License : BSD-style (see xmonad/LICENSE)
--
-- Maintainer : email@address.com
-- Stability : unstable
-- Portability : unportable
--
-- A tabbed layout for the Xmonad Window Manager
--
-----------------------------------------------------------------------------
module XMonadContrib.Tabbed (
-- * Usage:
-- $usage
tabbed
, Shrinker, shrinkText
, TConf (..), defaultTConf
) where
import Control.Monad ( forM )
import Graphics.X11.Xlib
import XMonad
import XMonadContrib.Decoration
import Operations ( focus, initColor )
import qualified StackSet as W
import XMonadContrib.NamedWindows
-- $usage
-- You can use this module with the following in your configuration file:
--
-- > import XMonadContrib.Tabbed
-- > import XMonadContrib.SimpleStacking
--
-- > defaultLayouts :: [Layout]
-- > defaultLayouts = [ simpleStacking $ tabbed shrinkText defaultTConf
-- > , ... ]
--
-- You can also edit the default configuration options.
--
-- > myconfig = defaultTConf { bgColor = "#FF0000"
-- > , textColor = "#00FF00"}
--
-- and
--
-- > defaultLayouts = [ simpleStacking $ tabbed shrinkText myconfig
-- > , ... ]
data TConf =
TConf { activeColor :: String
, inactiveColor :: String
, bgColor :: String
, textColor :: String
, fontName :: String
, tabSize :: Int
} deriving (Show, Read)
defaultTConf :: TConf
defaultTConf =
TConf { activeColor ="#BBBBBB"
, inactiveColor = "#888888"
, bgColor = "#000000"
, textColor = "#000000"
, fontName = "-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*"
, tabSize = 20
}
tabbed :: Shrinker -> TConf -> Layout Window
tabbed shrinkT config = Layout { doLayout = dolay shrinkT config, modifyLayout = const (return Nothing) }
dolay :: Shrinker -> TConf -> Rectangle -> W.Stack Window -> X [(Window, Rectangle)]
dolay _ _ sc (W.Stack w [] []) = return [(w,sc)]
dolay shr conf sc@(Rectangle x y wid _) s = withDisplay $ \dpy ->
do activecolor <- io $ initColor dpy $ activeColor conf
inactivecolor <- io $ initColor dpy $ inactiveColor conf
textcolor <- io $ initColor dpy $ textColor conf
bgcolor <- io $ initColor dpy $ bgColor conf
let ws = W.integrate s
ts = gentabs conf x y wid (length ws)
tws = zip ts ws
maketab (t,ow) = newDecoration ow t 1 bgcolor activecolor (fontName conf) (drawtab t ow) (focus ow)
drawtab r@(Rectangle _ _ wt ht) ow d w' gc fn =
do nw <- getName ow
let tabcolor = if W.focus s == ow then activecolor else inactivecolor
io $ setForeground d gc tabcolor
io $ fillRectangles d w' gc [Rectangle 0 0 wt ht]
io $ setForeground d gc textcolor
centerText d w' gc fn r (show nw)
centerText d w' gc fontst (Rectangle _ _ wt ht) name =
do let (_,asc,_,_) = textExtents fontst name
name' = shrinkWhile shr (\n -> textWidth fontst n >
fromIntegral wt - fromIntegral (ht `div` 2)) name
width = textWidth fontst name'
io $ drawString d w' gc
(fromIntegral (wt `div` 2) - fromIntegral (width `div` 2))
((fromIntegral ht + fromIntegral asc) `div` 2) name'
forM tws maketab
return [(W.focus s, shrink conf sc)]
type Shrinker = String -> [String]
shrinkWhile :: Shrinker -> (String -> Bool) -> String -> String
shrinkWhile sh p x = sw $ sh x
where sw [n] = n
sw [] = ""
sw (n:ns) | p n = sw ns
| otherwise = n
shrinkText :: Shrinker
shrinkText "" = [""]
shrinkText cs = cs : shrinkText (init cs)
shrink :: TConf -> Rectangle -> Rectangle
shrink c (Rectangle x y w h) = Rectangle x (y + fromIntegral (tabSize c)) w (h - fromIntegral (tabSize c))
gentabs :: TConf -> Position -> Position -> Dimension -> Int -> [Rectangle]
gentabs _ _ _ _ 0 = []
gentabs c x y w num = Rectangle x y (wid - 2) (fromIntegral (tabSize c) - 2)
: gentabs c (x + fromIntegral wid) y (w - wid) (num - 1)
where wid = w `div` (fromIntegral num)