{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances, FlexibleContexts, PatternGuards #-}
module XMonad.Layout.Master (
mastered,
fixMastered,
multimastered,
AddMaster,
) where
import XMonad
import qualified XMonad.StackSet as S
import XMonad.Layout.LayoutModifier
import Control.Monad
data AddMaster a = AddMaster Int Rational Rational deriving (Show, Read)
multimastered :: (LayoutClass l a) =>
Int
-> Rational
-> Rational
-> l a
-> ModifiedLayout AddMaster l a
multimastered k delta frac = ModifiedLayout $ AddMaster k delta frac
mastered :: (LayoutClass l a) =>
Rational
-> Rational
-> l a
-> ModifiedLayout AddMaster l a
mastered delta frac = multimastered 1 delta frac
instance LayoutModifier AddMaster Window where
modifyLayout (AddMaster k delta frac) = applyMaster False k delta frac
modifierDescription _ = "Mastered"
pureMess (AddMaster k delta frac) m
| Just Shrink <- fromMessage m = Just $ AddMaster k delta (frac-delta)
| Just Expand <- fromMessage m = Just $ AddMaster k delta (frac+delta)
| Just (IncMasterN d) <- fromMessage m = Just $ AddMaster (max 1 (k+d)) delta frac
pureMess _ _ = Nothing
data FixMaster a = FixMaster (AddMaster a) deriving (Show, Read)
instance LayoutModifier FixMaster Window where
modifyLayout (FixMaster (AddMaster k d f)) = applyMaster True k d f
modifierDescription (FixMaster a) = "Fix" ++ modifierDescription a
pureMess (FixMaster a) m = liftM FixMaster (pureMess a m)
fixMastered :: (LayoutClass l a) =>
Rational
-> Rational
-> l a
-> ModifiedLayout FixMaster l a
fixMastered delta frac = ModifiedLayout . FixMaster $ AddMaster 1 delta frac
applyMaster :: (LayoutClass l Window) =>
Bool
-> Int
-> Rational
-> Rational
-> S.Workspace WorkspaceId (l Window) Window
-> Rectangle
-> X ([(Window, Rectangle)], Maybe (l Window))
applyMaster f k _ frac wksp rect = do
let st= S.stack wksp
let ws = S.integrate' $ st
let n = length ws + fromEnum f
if n > 1 then do
if(n<=k) then
return ((divideCol rect ws), Nothing)
else do
let m = take k ws
let (mr, sr) = splitHorizontallyBy frac rect
let nst = st>>= S.filter (\w -> not (w `elem` m))
wrs <- runLayout (wksp {S.stack = nst}) sr
return ((divideCol mr m) ++ (fst wrs), snd wrs)
else runLayout wksp rect
shiftD :: Position -> Rectangle -> Rectangle
shiftD s (Rectangle x y w h) = Rectangle x (y+s) w h
divideCol :: Rectangle -> [a] -> [(a, Rectangle)]
divideCol (Rectangle x y w h) ws = zip ws rects
where n = length ws
oneH = fromIntegral h `div` n
oneRect = Rectangle x y w (fromIntegral oneH)
rects = take n $ iterate (shiftD (fromIntegral oneH)) oneRect