    {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Layout.OneBig
    -- Description :  Place one window at top left corner, and other windows at the top.
    -- Copyright   :  (c) 2009 Ilya Portnov
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  Ilya Portnov <portnov84@rambler.ru>
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Provides layout named OneBig. It places one (master) window at top left corner of screen, and other (slave) windows at top
    --
    -----------------------------------------------------------------------------

    module XMonad.Layout.OneBig (
                                 -- * Usage
                                 -- $usage
                                 OneBig (..)
                                ) where
    import XMonad
    import qualified XMonad.StackSet as W

    -- $usage
    -- This module defines layout named OneBig. It places one (master)
    -- window at top left, and other (slave) windows at right and at
    -- bottom of master. It tries to give equal space for each slave
    -- window.
    --
    -- You can use this module by adding following in your @xmonad.hs@:
    --
    -- > import XMonad.Layout.OneBig
    --
    -- Then add layouts to your layoutHook:
    --
    -- > myLayoutHook = OneBig (3/4) (3/4) ||| ...
    --
    -- In this example, master window will occupy 3/4 of screen width and
    -- 3/4 of screen height.

    -- | Data type for layout
    data OneBig a = OneBig Float Float deriving (ReadPrec [OneBig a]
    ReadPrec (OneBig a)
    Int -> ReadS (OneBig a)
    ReadS [OneBig a]
    (Int -> ReadS (OneBig a))
    -> ReadS [OneBig a]
    -> ReadPrec (OneBig a)
    -> ReadPrec [OneBig a]
    -> Read (OneBig a)
    forall a. ReadPrec [OneBig a]
    forall a. ReadPrec (OneBig a)
    forall a. Int -> ReadS (OneBig a)
    forall a. ReadS [OneBig a]
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: forall a. Int -> ReadS (OneBig a)
    readsPrec :: Int -> ReadS (OneBig a)
    $creadList :: forall a. ReadS [OneBig a]
    readList :: ReadS [OneBig a]
    $creadPrec :: forall a. ReadPrec (OneBig a)
    readPrec :: ReadPrec (OneBig a)
    $creadListPrec :: forall a. ReadPrec [OneBig a]
    readListPrec :: ReadPrec [OneBig a]
    Read,Int -> OneBig a -> ShowS
    [OneBig a] -> ShowS
    OneBig a -> String
    (Int -> OneBig a -> ShowS)
    -> (OneBig a -> String) -> ([OneBig a] -> ShowS) -> Show (OneBig a)
    forall a. Int -> OneBig a -> ShowS
    forall a. [OneBig a] -> ShowS
    forall a. OneBig a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Int -> OneBig a -> ShowS
    showsPrec :: Int -> OneBig a -> ShowS
    $cshow :: forall a. OneBig a -> String
    show :: OneBig a -> String
    $cshowList :: forall a. [OneBig a] -> ShowS
    showList :: [OneBig a] -> ShowS
    Show)

    instance LayoutClass OneBig a where
      pureLayout :: OneBig a -> Rectangle -> Stack a -> [(a, Rectangle)]
    pureLayout = OneBig a -> Rectangle -> Stack a -> [(a, Rectangle)]
    forall a. OneBig a -> Rectangle -> Stack a -> [(a, Rectangle)]
    oneBigLayout
      pureMessage :: OneBig a -> SomeMessage -> Maybe (OneBig a)
    pureMessage = OneBig a -> SomeMessage -> Maybe (OneBig a)
    forall a. OneBig a -> SomeMessage -> Maybe (OneBig a)
    oneBigMessage

    -- | Processes Shrink/Expand messages
    oneBigMessage :: OneBig a -> SomeMessage -> Maybe (OneBig a)
    oneBigMessage :: forall a. OneBig a -> SomeMessage -> Maybe (OneBig a)
    oneBigMessage (OneBig Float
    cx Float
    cy) SomeMessage
    m = (Resize -> OneBig a) -> Maybe Resize -> Maybe (OneBig a)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Resize -> OneBig a
    forall {a}. Resize -> OneBig a
    resize (SomeMessage -> Maybe Resize
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    m)
        where resize :: Resize -> OneBig a
    resize Resize
    Shrink = Float -> Float -> OneBig a
    forall a. Float -> Float -> OneBig a
    OneBig (Float
    cxFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    -Float
    delta) (Float
    cyFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    -Float
    delta)
              resize Resize
    Expand = Float -> Float -> OneBig a
    forall a. Float -> Float -> OneBig a
    OneBig (Float
    cxFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    +Float
    delta) (Float
    cyFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    +Float
    delta)
              delta :: Float
    delta = Float
    3Float -> Float -> Float
    forall a. Fractional a => a -> a -> a
    /Float
    100

    -- | Main layout function
    oneBigLayout :: OneBig a -> Rectangle -> W.Stack a -> [(a, Rectangle)]
    oneBigLayout :: forall a. OneBig a -> Rectangle -> Stack a -> [(a, Rectangle)]
    oneBigLayout (OneBig Float
    cx Float
    cy) Rectangle
    rect Stack a
    stack = [(a
    master,Rectangle
    masterRect)]
                                          [(a, Rectangle)] -> [(a, Rectangle)] -> [(a, Rectangle)]
    forall a. [a] -> [a] -> [a]
    ++ Rectangle -> [a] -> [(a, Rectangle)]
    forall a. Rectangle -> [a] -> [(a, Rectangle)]
    divideBottom Rectangle
    bottomRect [a]
    bottomWs
                                          [(a, Rectangle)] -> [(a, Rectangle)] -> [(a, Rectangle)]
    forall a. [a] -> [a] -> [a]
    ++ Rectangle -> [a] -> [(a, Rectangle)]
    forall a. Rectangle -> [a] -> [(a, Rectangle)]
    divideRight Rectangle
    rightRect [a]
    rightWs
          where ws :: [a]
    ws = Stack a -> [a]
    forall a. Stack a -> [a]
    W.integrate Stack a
    stack
                n :: Int
    n = [a] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    ws
                ht :: Rectangle -> Dimension
    ht (Rectangle Position
    _ Position
    _ Dimension
    _ Dimension
    hh) = Dimension
    hh
                wd :: Rectangle -> Dimension
    wd (Rectangle Position
    _ Position
    _ Dimension
    ww Dimension
    _) = Dimension
    ww
                h' :: Dimension
    h' = Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Rectangle -> Dimension
    ht Rectangle
    rect)Float -> Float -> Float
    forall a. Num a => a -> a -> a
    *Float
    cy)
                w :: Dimension
    w = Rectangle -> Dimension
    wd Rectangle
    rect
                m :: Int
    m = Int -> Dimension -> Dimension -> Int
    calcBottomWs Int
    n Dimension
    w Dimension
    h'
                master :: a
    master = [a] -> a
    forall a. HasCallStack => [a] -> a
    head [a]
    ws
                other :: [a]
    other  = [a] -> [a]
    forall a. HasCallStack => [a] -> [a]
    tail [a]
    ws
                bottomWs :: [a]
    bottomWs = Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    m [a]
    other
                rightWs :: [a]
    rightWs = Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    drop Int
    m [a]
    other
                masterRect :: Rectangle
    masterRect = Int -> Int -> Float -> Float -> Rectangle -> Rectangle
    cmaster Int
    n Int
    m Float
    cx Float
    cy Rectangle
    rect
                bottomRect :: Rectangle
    bottomRect = Float -> Rectangle -> Rectangle
    cbottom Float
    cy Rectangle
    rect
                rightRect :: Rectangle
    rightRect  = Float -> Float -> Rectangle -> Rectangle
    cright Float
    cx Float
    cy Rectangle
    rect

    -- | Calculate how many windows must be placed at bottom
    calcBottomWs :: Int -> Dimension -> Dimension -> Int
    calcBottomWs :: Int -> Dimension -> Dimension -> Int
    calcBottomWs Int
    n Dimension
    w Dimension
    h' = case Int
    n of
                            Int
    1 -> Int
    0
                            Int
    2 -> Int
    1
                            Int
    3 -> Int
    2
                            Int
    4 -> Int
    2
                            Int
    _ -> Dimension -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    wInt -> Int -> Int
    forall a. Num a => a -> a -> a
    *(Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    1) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Dimension -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension
    h'Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    +Dimension -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    w)

    -- | Calculate rectangle for master window
    cmaster:: Int -> Int -> Float -> Float -> Rectangle -> Rectangle
    cmaster :: Int -> Int -> Float -> Float -> Rectangle -> Rectangle
    cmaster Int
    n Int
    m Float
    cx Float
    cy (Rectangle Position
    x Position
    y Dimension
    sw Dimension
    sh) = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x Position
    y Dimension
    w Dimension
    h
        where w :: Dimension
    w = if Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    mInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1 then
                    Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    swFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    *Float
    cx)
                  else
                    Dimension
    sw
              h :: Dimension
    h = if Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    1 then
                    Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    shFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    *Float
    cy)
                  else
                    Dimension
    sh

    -- | Calculate rectangle for bottom windows
    cbottom:: Float -> Rectangle -> Rectangle
    cbottom :: Float -> Rectangle -> Rectangle
    cbottom Float
    cy (Rectangle Position
    sx Position
    sy Dimension
    sw Dimension
    sh) = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    sx Position
    y Dimension
    sw Dimension
    h
        where h :: Dimension
    h = Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    shFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    *(Float
    1Float -> Float -> Float
    forall a. Num a => a -> a -> a
    -Float
    cy))
              y :: Position
    y = Float -> Position
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    shFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    *Float
    cyFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    +Position -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Position
    sy)

    -- | Calculate rectangle for right windows
    cright:: Float -> Float -> Rectangle -> Rectangle
    cright :: Float -> Float -> Rectangle -> Rectangle
    cright Float
    cx Float
    cy (Rectangle Position
    sx Position
    sy Dimension
    sw Dimension
    sh) = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x Position
    sy Dimension
    w Dimension
    h
        where w :: Dimension
    w = Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    swFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    *(Float
    1Float -> Float -> Float
    forall a. Num a => a -> a -> a
    -Float
    cx))
              x :: Position
    x = Float -> Position
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    swFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    *Float
    cxFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    +Position -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Position
    sx)
              h :: Dimension
    h = Float -> Dimension
    forall b. Integral b => Float -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    shFloat -> Float -> Float
    forall a. Num a => a -> a -> a
    *Float
    cy)

    -- | Divide bottom rectangle between windows
    divideBottom :: Rectangle -> [a] -> [(a, Rectangle)]
    divideBottom :: forall a. Rectangle -> [a] -> [(a, Rectangle)]
    divideBottom (Rectangle Position
    x Position
    y Dimension
    w Dimension
    h) [a]
    ws = [a] -> [Rectangle] -> [(a, Rectangle)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [a]
    ws [Rectangle]
    rects
        where n :: Int
    n = [a] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    ws
              oneW :: Int
    oneW = Dimension -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    w Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    n
              oneRect :: Rectangle
    oneRect = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x Position
    y (Int -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    oneW) Dimension
    h
              rects :: [Rectangle]
    rects = Int -> [Rectangle] -> [Rectangle]
    forall a. Int -> [a] -> [a]
    take Int
    n ([Rectangle] -> [Rectangle]) -> [Rectangle] -> [Rectangle]
    forall a b. (a -> b) -> a -> b
    $ (Rectangle -> Rectangle) -> Rectangle -> [Rectangle]
    forall a. (a -> a) -> a -> [a]
    iterate (Position -> Rectangle -> Rectangle
    shiftR (Int -> Position
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    oneW)) Rectangle
    oneRect

    -- | Divide right rectangle between windows
    divideRight :: Rectangle -> [a] -> [(a, Rectangle)]
    divideRight :: forall a. Rectangle -> [a] -> [(a, Rectangle)]
    divideRight (Rectangle Position
    x Position
    y Dimension
    w Dimension
    h) [a]
    ws = if Int
    nInt -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Int
    0 then [] else [a] -> [Rectangle] -> [(a, Rectangle)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [a]
    ws [Rectangle]
    rects
        where n :: Int
    n = [a] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    ws
              oneH :: Int
    oneH = Dimension -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    h Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    n
              oneRect :: Rectangle
    oneRect = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x Position
    y Dimension
    w (Int -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    oneH)
              rects :: [Rectangle]
    rects = Int -> [Rectangle] -> [Rectangle]
    forall a. Int -> [a] -> [a]
    take Int
    n ([Rectangle] -> [Rectangle]) -> [Rectangle] -> [Rectangle]
    forall a b. (a -> b) -> a -> b
    $ (Rectangle -> Rectangle) -> Rectangle -> [Rectangle]
    forall a. (a -> a) -> a -> [a]
    iterate (Position -> Rectangle -> Rectangle
    shiftB (Int -> Position
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    oneH)) Rectangle
    oneRect

    -- | Shift rectangle right
    shiftR :: Position -> Rectangle -> Rectangle
    shiftR :: Position -> Rectangle -> Rectangle
    shiftR Position
    s (Rectangle Position
    x Position
    y Dimension
    w Dimension
    h) = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle (Position
    xPosition -> Position -> Position
    forall a. Num a => a -> a -> a
    +Position
    s) Position
    y Dimension
    w Dimension
    h

    -- | Shift rectangle bottom
    shiftB :: Position -> Rectangle -> Rectangle
    shiftB :: Position -> Rectangle -> Rectangle
    shiftB Position
    s (Rectangle Position
    x Position
    y Dimension
    w Dimension
    h) = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x (Position
    yPosition -> Position -> Position
    forall a. Num a => a -> a -> a
    +Position
    s) Dimension
    w Dimension
    h