{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TupleSections #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Layout.Dishes
-- Description :  A layout that stacks extra windows underneath the master windows.
-- Copyright   :  (c) Jeremy Apthorp
-- License     :  BSD-style (see LICENSE)
--
-- Maintainer  :  Jeremy Apthorp <nornagon@gmail.com>
-- Stability   :  unstable
-- Portability :  portable
--
-- Dishes is a layout that stacks extra windows underneath the master
-- windows.
--
-----------------------------------------------------------------------------

module XMonad.Layout.Dishes (
                              -- * Usage
                              -- $usage
                              Dishes (..)
                            ) where

import XMonad
import XMonad.StackSet (integrate)
import XMonad.Prelude (ap)

-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
--
-- > import XMonad.Layout.Dishes
--
-- Then edit your @layoutHook@ by adding the Dishes layout:
--
-- > myLayout = Dishes 2 (1/6) ||| Full ||| etc..
-- > main = xmonad def { layoutHook = myLayout }
--
-- For more detailed instructions on editing the layoutHook see:
--
-- "XMonad.Doc.Extending#Editing_the_layout_hook"

data Dishes a = Dishes Int Rational deriving (Int -> Dishes a -> ShowS
[Dishes a] -> ShowS
Dishes a -> String
(Int -> Dishes a -> ShowS)
-> (Dishes a -> String) -> ([Dishes a] -> ShowS) -> Show (Dishes a)
forall a. Int -> Dishes a -> ShowS
forall a. [Dishes a] -> ShowS
forall a. Dishes a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Dishes a] -> ShowS
$cshowList :: forall a. [Dishes a] -> ShowS
show :: Dishes a -> String
$cshow :: forall a. Dishes a -> String
showsPrec :: Int -> Dishes a -> ShowS
$cshowsPrec :: forall a. Int -> Dishes a -> ShowS
Show, ReadPrec [Dishes a]
ReadPrec (Dishes a)
Int -> ReadS (Dishes a)
ReadS [Dishes a]
(Int -> ReadS (Dishes a))
-> ReadS [Dishes a]
-> ReadPrec (Dishes a)
-> ReadPrec [Dishes a]
-> Read (Dishes a)
forall a. ReadPrec [Dishes a]
forall a. ReadPrec (Dishes a)
forall a. Int -> ReadS (Dishes a)
forall a. ReadS [Dishes a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Dishes a]
$creadListPrec :: forall a. ReadPrec [Dishes a]
readPrec :: ReadPrec (Dishes a)
$creadPrec :: forall a. ReadPrec (Dishes a)
readList :: ReadS [Dishes a]
$creadList :: forall a. ReadS [Dishes a]
readsPrec :: Int -> ReadS (Dishes a)
$creadsPrec :: forall a. Int -> ReadS (Dishes a)
Read)
instance LayoutClass Dishes a where
    doLayout :: Dishes a
-> Rectangle -> Stack a -> X ([(a, Rectangle)], Maybe (Dishes a))
doLayout (Dishes Int
nmaster Rational
h) Rectangle
r =
        ([(a, Rectangle)], Maybe (Dishes a))
-> X ([(a, Rectangle)], Maybe (Dishes a))
forall (m :: * -> *) a. Monad m => a -> m a
return (([(a, Rectangle)], Maybe (Dishes a))
 -> X ([(a, Rectangle)], Maybe (Dishes a)))
-> (Stack a -> ([(a, Rectangle)], Maybe (Dishes a)))
-> Stack a
-> X ([(a, Rectangle)], Maybe (Dishes a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (, Maybe (Dishes a)
forall a. Maybe a
Nothing) ([(a, Rectangle)] -> ([(a, Rectangle)], Maybe (Dishes a)))
-> (Stack a -> [(a, Rectangle)])
-> Stack a
-> ([(a, Rectangle)], Maybe (Dishes a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
        ([a] -> [Rectangle] -> [(a, Rectangle)])
-> ([a] -> [Rectangle]) -> [a] -> [(a, Rectangle)]
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap [a] -> [Rectangle] -> [(a, Rectangle)]
forall a b. [a] -> [b] -> [(a, b)]
zip (Rational -> Rectangle -> Int -> Int -> [Rectangle]
dishes Rational
h Rectangle
r Int
nmaster (Int -> [Rectangle]) -> ([a] -> Int) -> [a] -> [Rectangle]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length) ([a] -> [(a, Rectangle)])
-> (Stack a -> [a]) -> Stack a -> [(a, Rectangle)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stack a -> [a]
forall a. Stack a -> [a]
integrate
    pureMessage :: Dishes a -> SomeMessage -> Maybe (Dishes a)
pureMessage (Dishes Int
nmaster Rational
h) SomeMessage
m = (IncMasterN -> Dishes a) -> Maybe IncMasterN -> Maybe (Dishes a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IncMasterN -> Dishes a
forall a. IncMasterN -> Dishes a
incmastern (SomeMessage -> Maybe IncMasterN
forall m. Message m => SomeMessage -> Maybe m
fromMessage SomeMessage
m)
        where incmastern :: IncMasterN -> Dishes a
incmastern (IncMasterN Int
d) = Int -> Rational -> Dishes a
forall a. Int -> Rational -> Dishes a
Dishes (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
nmasterInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
d)) Rational
h

dishes :: Rational -> Rectangle -> Int -> Int -> [Rectangle]
dishes :: Rational -> Rectangle -> Int -> Int -> [Rectangle]
dishes Rational
h Rectangle
s Int
nmaster Int
n = if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
nmaster
                        then Int -> Rectangle -> [Rectangle]
splitHorizontally Int
n Rectangle
s
                        else [Rectangle]
ws
 where
    (Rectangle
m,Rectangle
rest) = Rational -> Rectangle -> (Rectangle, Rectangle)
forall r. RealFrac r => r -> Rectangle -> (Rectangle, Rectangle)
splitVerticallyBy (Rational
1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Int -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
nmaster) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
h) Rectangle
s
    ws :: [Rectangle]
ws = Int -> Rectangle -> [Rectangle]
splitHorizontally Int
nmaster Rectangle
m [Rectangle] -> [Rectangle] -> [Rectangle]
forall a. [a] -> [a] -> [a]
++ Int -> Rectangle -> [Rectangle]
splitVertically (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
nmaster) Rectangle
rest