    {-# 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.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
    -- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial> and
    -- "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
    $cshowsPrec :: forall a. Int -> Dishes a -> ShowS
    showsPrec :: Int -> Dishes a -> ShowS
    $cshow :: forall a. Dishes a -> String
    show :: Dishes a -> String
    $cshowList :: forall a. [Dishes a] -> ShowS
    showList :: [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
    $creadsPrec :: forall a. Int -> ReadS (Dishes a)
    readsPrec :: Int -> ReadS (Dishes a)
    $creadList :: forall a. ReadS [Dishes a]
    readList :: ReadS [Dishes a]
    $creadPrec :: forall a. ReadPrec (Dishes a)
    readPrec :: ReadPrec (Dishes a)
    $creadListPrec :: forall a. ReadPrec [Dishes a]
    readListPrec :: ReadPrec [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 a. a -> X 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 a. [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 a b. (a -> b) -> Maybe a -> Maybe b
    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