    {-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeSynonymInstances #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Layout.MosaicAlt
    -- Copyright   :  (c) 2007 James Webb
    -- License     :  BSD-style (see xmonad/LICENSE)
    --
    -- Maintainer  :  xmonad#jwebb,sygneca,com
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- A layout which gives each window a specified amount of screen space
    -- relative to the others. Compared to the 'Mosaic' layout, this one
    -- divides the space in a more balanced way.
    --
    -----------------------------------------------------------------------------

    module XMonad.Layout.MosaicAlt (
            -- * Usage:
            -- $usage
            MosaicAlt(..)
            , shrinkWindowAlt
            , expandWindowAlt
            , tallWindowAlt
            , wideWindowAlt
            , resetAlt

            , Params, Param
            , HandleWindowAlt
        ) where

    import XMonad
    import qualified XMonad.StackSet as W
    import qualified Data.Map as M
    import Data.List ( sortBy )
    import Data.Ratio

    -- $usage
    -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
    --
    -- > import XMonad.Layout.MosaicAlt
    -- > import qualified Data.Map as M
    --
    -- Then edit your @layoutHook@ by adding the MosaicAlt layout:
    --
    -- > myLayout = MosaicAlt M.empty ||| Full ||| etc..
    -- > main = xmonad def { layoutHook = myLayout }
    --
    -- For more detailed instructions on editing the layoutHook see:
    --
    -- "XMonad.Doc.Extending#Editing_the_layout_hook"
    --
    -- In the key-bindings, do something like:
    --
    -- >     , ((modm .|. shiftMask  , xK_a    ), withFocused (sendMessage . expandWindowAlt))
    -- >     , ((modm .|. shiftMask  , xK_z    ), withFocused (sendMessage . shrinkWindowAlt))
    -- >     , ((modm .|. shiftMask  , xK_s    ), withFocused (sendMessage . tallWindowAlt))
    -- >     , ((modm .|. shiftMask  , xK_d    ), withFocused (sendMessage . wideWindowAlt))
    -- >     , ((modm .|. controlMask, xK_space), sendMessage resetAlt)
    -- >     ...
    --
    -- For detailed instruction on editing the key binding see:
    --
    -- "XMonad.Doc.Extending#Editing_key_bindings".

    data HandleWindowAlt =
        ShrinkWindowAlt Window
        | ExpandWindowAlt Window
        | TallWindowAlt Window
        | WideWindowAlt Window
        | ResetAlt
        deriving ( Typeable, HandleWindowAlt -> HandleWindowAlt -> Bool
    (HandleWindowAlt -> HandleWindowAlt -> Bool)
    -> (HandleWindowAlt -> HandleWindowAlt -> Bool)
    -> Eq HandleWindowAlt
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: HandleWindowAlt -> HandleWindowAlt -> Bool
    $c/= :: HandleWindowAlt -> HandleWindowAlt -> Bool
    == :: HandleWindowAlt -> HandleWindowAlt -> Bool
    $c== :: HandleWindowAlt -> HandleWindowAlt -> Bool
    Eq )
    instance Message HandleWindowAlt
    shrinkWindowAlt, expandWindowAlt :: Window -> HandleWindowAlt
    tallWindowAlt, wideWindowAlt :: Window -> HandleWindowAlt
    shrinkWindowAlt :: Window -> HandleWindowAlt
    shrinkWindowAlt = Window -> HandleWindowAlt
    ShrinkWindowAlt
    expandWindowAlt :: Window -> HandleWindowAlt
    expandWindowAlt = Window -> HandleWindowAlt
    ExpandWindowAlt
    tallWindowAlt :: Window -> HandleWindowAlt
    tallWindowAlt = Window -> HandleWindowAlt
    TallWindowAlt
    wideWindowAlt :: Window -> HandleWindowAlt
    wideWindowAlt = Window -> HandleWindowAlt
    WideWindowAlt
    resetAlt :: HandleWindowAlt
    resetAlt :: HandleWindowAlt
    resetAlt = HandleWindowAlt
    ResetAlt

    data Param = Param { Param -> Rational
    area, Param -> Rational
    aspect :: Rational } deriving ( Int -> Param -> ShowS
    [Param] -> ShowS
    Param -> String
    (Int -> Param -> ShowS)
    -> (Param -> String) -> ([Param] -> ShowS) -> Show Param
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [Param] -> ShowS
    $cshowList :: [Param] -> ShowS
    show :: Param -> String
    $cshow :: Param -> String
    showsPrec :: Int -> Param -> ShowS
    $cshowsPrec :: Int -> Param -> ShowS
    Show, ReadPrec [Param]
    ReadPrec Param
    Int -> ReadS Param
    ReadS [Param]
    (Int -> ReadS Param)
    -> ReadS [Param]
    -> ReadPrec Param
    -> ReadPrec [Param]
    -> Read Param
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    readListPrec :: ReadPrec [Param]
    $creadListPrec :: ReadPrec [Param]
    readPrec :: ReadPrec Param
    $creadPrec :: ReadPrec Param
    readList :: ReadS [Param]
    $creadList :: ReadS [Param]
    readsPrec :: Int -> ReadS Param
    $creadsPrec :: Int -> ReadS Param
    Read )
    type Params = M.Map Window Param
    data MosaicAlt a = MosaicAlt Params deriving ( Int -> MosaicAlt a -> ShowS
    [MosaicAlt a] -> ShowS
    MosaicAlt a -> String
    (Int -> MosaicAlt a -> ShowS)
    -> (MosaicAlt a -> String)
    -> ([MosaicAlt a] -> ShowS)
    -> Show (MosaicAlt a)
    forall a. Int -> MosaicAlt a -> ShowS
    forall a. [MosaicAlt a] -> ShowS
    forall a. MosaicAlt a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [MosaicAlt a] -> ShowS
    $cshowList :: forall a. [MosaicAlt a] -> ShowS
    show :: MosaicAlt a -> String
    $cshow :: forall a. MosaicAlt a -> String
    showsPrec :: Int -> MosaicAlt a -> ShowS
    $cshowsPrec :: forall a. Int -> MosaicAlt a -> ShowS
    Show, ReadPrec [MosaicAlt a]
    ReadPrec (MosaicAlt a)
    Int -> ReadS (MosaicAlt a)
    ReadS [MosaicAlt a]
    (Int -> ReadS (MosaicAlt a))
    -> ReadS [MosaicAlt a]
    -> ReadPrec (MosaicAlt a)
    -> ReadPrec [MosaicAlt a]
    -> Read (MosaicAlt a)
    forall a. ReadPrec [MosaicAlt a]
    forall a. ReadPrec (MosaicAlt a)
    forall a. Int -> ReadS (MosaicAlt a)
    forall a. ReadS [MosaicAlt a]
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    readListPrec :: ReadPrec [MosaicAlt a]
    $creadListPrec :: forall a. ReadPrec [MosaicAlt a]
    readPrec :: ReadPrec (MosaicAlt a)
    $creadPrec :: forall a. ReadPrec (MosaicAlt a)
    readList :: ReadS [MosaicAlt a]
    $creadList :: forall a. ReadS [MosaicAlt a]
    readsPrec :: Int -> ReadS (MosaicAlt a)
    $creadsPrec :: forall a. Int -> ReadS (MosaicAlt a)
    Read )

    instance LayoutClass MosaicAlt Window where
        description :: MosaicAlt Window -> String
    description _ = "MosaicAlt"
        doLayout :: MosaicAlt Window
    -> Rectangle
    -> Stack Window
    -> X ([(Window, Rectangle)], Maybe (MosaicAlt Window))
    doLayout (MosaicAlt params :: Params
    params) rect :: Rectangle
    rect stack :: Stack Window
    stack =
                ([(Window, Rectangle)], Maybe (MosaicAlt Window))
    -> X ([(Window, Rectangle)], Maybe (MosaicAlt Window))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Rectangle -> Stack Window -> Params -> [(Window, Rectangle)]
    arrange Rectangle
    rect Stack Window
    stack Params
    params', MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a. a -> Maybe a
    Just (MosaicAlt Window -> Maybe (MosaicAlt Window))
    -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a b. (a -> b) -> a -> b
    $ Params -> MosaicAlt Window
    forall a. Params -> MosaicAlt a
    MosaicAlt Params
    params')
            where
                params' :: Params
    params' = [Window] -> Params -> Params
    forall k. Ord k => [k] -> Map k Param -> Map k Param
    ins (Stack Window -> [Window]
    forall a. Stack a -> [a]
    W.up Stack Window
    stack) (Params -> Params) -> Params -> Params
    forall a b. (a -> b) -> a -> b
    $ [Window] -> Params -> Params
    forall k. Ord k => [k] -> Map k Param -> Map k Param
    ins (Stack Window -> [Window]
    forall a. Stack a -> [a]
    W.down Stack Window
    stack) (Params -> Params) -> Params -> Params
    forall a b. (a -> b) -> a -> b
    $ [Window] -> Params -> Params
    forall k. Ord k => [k] -> Map k Param -> Map k Param
    ins [Stack Window -> Window
    forall a. Stack a -> a
    W.focus Stack Window
    stack] Params
    params
                ins :: [k] -> Map k Param -> Map k Param
    ins wins :: [k]
    wins as :: Map k Param
    as = (Map k Param -> Map k Param -> Map k Param)
    -> Map k Param -> [Map k Param] -> Map k Param
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl Map k Param -> Map k Param -> Map k Param
    forall k a. Ord k => Map k a -> Map k a -> Map k a
    M.union Map k Param
    as ([Map k Param] -> Map k Param) -> [Map k Param] -> Map k Param
    forall a b. (a -> b) -> a -> b
    $ (k -> Map k Param) -> [k] -> [Map k Param]
    forall a b. (a -> b) -> [a] -> [b]
    map (k -> Param -> Map k Param
    forall k a. k -> a -> Map k a
    `M.singleton` (Rational -> Rational -> Param
    Param 1 1.5)) [k]
    wins

        handleMessage :: MosaicAlt Window -> SomeMessage -> X (Maybe (MosaicAlt Window))
    handleMessage (MosaicAlt params :: Params
    params) msg :: SomeMessage
    msg = Maybe (MosaicAlt Window) -> X (Maybe (MosaicAlt Window))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (MosaicAlt Window) -> X (Maybe (MosaicAlt Window)))
    -> Maybe (MosaicAlt Window) -> X (Maybe (MosaicAlt Window))
    forall a b. (a -> b) -> a -> b
    $ case SomeMessage -> Maybe HandleWindowAlt
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    msg of
            Just (ShrinkWindowAlt w :: Window
    w) -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a. a -> Maybe a
    Just (MosaicAlt Window -> Maybe (MosaicAlt Window))
    -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a b. (a -> b) -> a -> b
    $ Params -> MosaicAlt Window
    forall a. Params -> MosaicAlt a
    MosaicAlt (Params -> MosaicAlt Window) -> Params -> MosaicAlt Window
    forall a b. (a -> b) -> a -> b
    $ Params -> Window -> Rational -> Rational -> Params
    alter Params
    params Window
    w (4 Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    % 5) 1
            Just (ExpandWindowAlt w :: Window
    w) -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a. a -> Maybe a
    Just (MosaicAlt Window -> Maybe (MosaicAlt Window))
    -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a b. (a -> b) -> a -> b
    $ Params -> MosaicAlt Window
    forall a. Params -> MosaicAlt a
    MosaicAlt (Params -> MosaicAlt Window) -> Params -> MosaicAlt Window
    forall a b. (a -> b) -> a -> b
    $ Params -> Window -> Rational -> Rational -> Params
    alter Params
    params Window
    w (6 Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    % 5) 1
            Just (TallWindowAlt w :: Window
    w) -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a. a -> Maybe a
    Just (MosaicAlt Window -> Maybe (MosaicAlt Window))
    -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a b. (a -> b) -> a -> b
    $ Params -> MosaicAlt Window
    forall a. Params -> MosaicAlt a
    MosaicAlt (Params -> MosaicAlt Window) -> Params -> MosaicAlt Window
    forall a b. (a -> b) -> a -> b
    $ Params -> Window -> Rational -> Rational -> Params
    alter Params
    params Window
    w 1 (3 Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    % 4)
            Just (WideWindowAlt w :: Window
    w) -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a. a -> Maybe a
    Just (MosaicAlt Window -> Maybe (MosaicAlt Window))
    -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a b. (a -> b) -> a -> b
    $ Params -> MosaicAlt Window
    forall a. Params -> MosaicAlt a
    MosaicAlt (Params -> MosaicAlt Window) -> Params -> MosaicAlt Window
    forall a b. (a -> b) -> a -> b
    $ Params -> Window -> Rational -> Rational -> Params
    alter Params
    params Window
    w 1 (5 Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    % 4)
            Just ResetAlt -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a. a -> Maybe a
    Just (MosaicAlt Window -> Maybe (MosaicAlt Window))
    -> MosaicAlt Window -> Maybe (MosaicAlt Window)
    forall a b. (a -> b) -> a -> b
    $ Params -> MosaicAlt Window
    forall a. Params -> MosaicAlt a
    MosaicAlt Params
    forall k a. Map k a
    M.empty
            _ -> Maybe (MosaicAlt Window)
    forall a. Maybe a
    Nothing

    -- Change requested params for a window.
    alter :: Params -> Window -> Rational -> Rational -> Params
    alter :: Params -> Window -> Rational -> Rational -> Params
    alter params :: Params
    params win :: Window
    win arDelta :: Rational
    arDelta asDelta :: Rational
    asDelta = case Window -> Params -> Maybe Param
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup Window
    win Params
    params of
        Just (Param ar :: Rational
    ar as :: Rational
    as) -> Window -> Param -> Params -> Params
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    M.insert Window
    win (Rational -> Rational -> Param
    Param (Rational
    ar Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Rational
    arDelta) (Rational
    as Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Rational
    asDelta)) Params
    params
        Nothing -> Window -> Param -> Params -> Params
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    M.insert Window
    win (Rational -> Rational -> Param
    Param Rational
    arDelta (1.5 Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Rational
    asDelta)) Params
    params

    -- Layout algorithm entry point.
    arrange :: Rectangle -> W.Stack Window -> Params -> [(Window, Rectangle)]
    arrange :: Rectangle -> Stack Window -> Params -> [(Window, Rectangle)]
    arrange rect :: Rectangle
    rect stack :: Stack Window
    stack params :: Params
    params = [(Window, Rectangle)]
    r
        where
            (_, r :: [(Window, Rectangle)]
    r) = Int
    -> Rectangle -> Tree -> Params -> (Double, [(Window, Rectangle)])
    findSplits 3 Rectangle
    rect Tree
    tree Params
    params
            tree :: Tree
    tree = [Window] -> Params -> Tree
    makeTree ((Window -> Window -> Ordering) -> [Window] -> [Window]
    forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy Window -> Window -> Ordering
    areaCompare [Window]
    wins) Params
    params
            wins :: [Window]
    wins = [Window] -> [Window]
    forall a. [a] -> [a]
    reverse (Stack Window -> [Window]
    forall a. Stack a -> [a]
    W.up Stack Window
    stack) [Window] -> [Window] -> [Window]
    forall a. [a] -> [a] -> [a]
    ++ Stack Window -> Window
    forall a. Stack a -> a
    W.focus Stack Window
    stack Window -> [Window] -> [Window]
    forall a. a -> [a] -> [a]
    : Stack Window -> [Window]
    forall a. Stack a -> [a]
    W.down Stack Window
    stack
            areaCompare :: Window -> Window -> Ordering
    areaCompare a :: Window
    a b :: Window
    b = Window -> Rational
    or1 Window
    b Rational -> Rational -> Ordering
    forall a. Ord a => a -> a -> Ordering
    `compare` Window -> Rational
    or1 Window
    a
            or1 :: Window -> Rational
    or1 w :: Window
    w = Rational -> (Param -> Rational) -> Maybe Param -> Rational
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe 1 Param -> Rational
    area (Maybe Param -> Rational) -> Maybe Param -> Rational
    forall a b. (a -> b) -> a -> b
    $ Window -> Params -> Maybe Param
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup Window
    w Params
    params

    -- Recursively group windows into a binary tree. Aim to balance the tree
    -- according to the total requested area in each branch.
    data Tree = Node (Rational, Tree) (Rational, Tree) | Leaf Window | None
    makeTree :: [Window] -> Params -> Tree
    makeTree :: [Window] -> Params -> Tree
    makeTree wins :: [Window]
    wins params :: Params
    params = case [Window]
    wins of
        [] -> Tree
    None
        [x :: Window
    x] -> Window -> Tree
    Leaf Window
    x
        _ -> (Rational, Tree) -> (Rational, Tree) -> Tree
    Node (Rational
    aArea, [Window] -> Params -> Tree
    makeTree [Window]
    aWins Params
    params) (Rational
    bArea, [Window] -> Params -> Tree
    makeTree [Window]
    bWins Params
    params)
            where ((aWins :: [Window]
    aWins, aArea :: Rational
    aArea), (bWins :: [Window]
    bWins, bArea :: Rational
    bArea)) = Params -> [Window] -> (([Window], Rational), ([Window], Rational))
    areaSplit Params
    params [Window]
    wins

    -- Split a list of windows in half by area.
    areaSplit :: Params -> [Window] -> (([Window], Rational), ([Window], Rational))
    areaSplit :: Params -> [Window] -> (([Window], Rational), ([Window], Rational))
    areaSplit params :: Params
    params wins :: [Window]
    wins = [Window]
    -> Rational
    -> [Window]
    -> Rational
    -> [Window]
    -> (([Window], Rational), ([Window], Rational))
    gather [] 0 [] 0 [Window]
    wins
        where
            gather :: [Window]
    -> Rational
    -> [Window]
    -> Rational
    -> [Window]
    -> (([Window], Rational), ([Window], Rational))
    gather a :: [Window]
    a aa :: Rational
    aa b :: [Window]
    b ba :: Rational
    ba (r :: Window
    r : rs :: [Window]
    rs) =
                if Rational
    aa Rational -> Rational -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Rational
    ba
                    then [Window]
    -> Rational
    -> [Window]
    -> Rational
    -> [Window]
    -> (([Window], Rational), ([Window], Rational))
    gather (Window
    r Window -> [Window] -> [Window]
    forall a. a -> [a] -> [a]
    : [Window]
    a) (Rational
    aa Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    + Window -> Rational
    or1 Window
    r) [Window]
    b Rational
    ba [Window]
    rs
                    else [Window]
    -> Rational
    -> [Window]
    -> Rational
    -> [Window]
    -> (([Window], Rational), ([Window], Rational))
    gather [Window]
    a Rational
    aa (Window
    r Window -> [Window] -> [Window]
    forall a. a -> [a] -> [a]
    : [Window]
    b) (Rational
    ba Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    + Window -> Rational
    or1 Window
    r) [Window]
    rs
            gather a :: [Window]
    a aa :: Rational
    aa b :: [Window]
    b ba :: Rational
    ba [] = (([Window] -> [Window]
    forall a. [a] -> [a]
    reverse [Window]
    a, Rational
    aa), ([Window]
    b, Rational
    ba))
            or1 :: Window -> Rational
    or1 w :: Window
    w = Rational -> (Param -> Rational) -> Maybe Param -> Rational
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe 1 Param -> Rational
    area (Maybe Param -> Rational) -> Maybe Param -> Rational
    forall a b. (a -> b) -> a -> b
    $ Window -> Params -> Maybe Param
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup Window
    w Params
    params

    -- Figure out which ways to split the space, by exhaustive search.
    -- Complexity is quadratic in the number of windows.
    findSplits :: Int -> Rectangle -> Tree -> Params -> (Double, [(Window, Rectangle)])
    findSplits :: Int
    -> Rectangle -> Tree -> Params -> (Double, [(Window, Rectangle)])
    findSplits _ _ None _ = (0, [])
    findSplits _ rect :: Rectangle
    rect (Leaf w :: Window
    w) params :: Params
    params = (Rectangle -> Window -> Params -> Double
    aspectBadness Rectangle
    rect Window
    w Params
    params, [(Window
    w, Rectangle
    rect)])
    findSplits depth :: Int
    depth rect :: Rectangle
    rect (Node (aArea :: Rational
    aArea, aTree :: Tree
    aTree) (bArea :: Rational
    bArea, bTree :: Tree
    bTree)) params :: Params
    params =
            if Double
    hBadness Double -> Double -> Bool
    forall a. Ord a => a -> a -> Bool
    < Double
    vBadness then (Double
    hBadness, [(Window, Rectangle)]
    hList) else (Double
    vBadness, [(Window, Rectangle)]
    vList)
        where
            (hBadness :: Double
    hBadness, hList :: [(Window, Rectangle)]
    hList) = (Rational -> Rectangle -> (Rectangle, Rectangle))
    -> (Double, [(Window, Rectangle)])
    trySplit Rational -> Rectangle -> (Rectangle, Rectangle)
    forall r. RealFrac r => r -> Rectangle -> (Rectangle, Rectangle)
    splitHorizontallyBy
            (vBadness :: Double
    vBadness, vList :: [(Window, Rectangle)]
    vList) = (Rational -> Rectangle -> (Rectangle, Rectangle))
    -> (Double, [(Window, Rectangle)])
    trySplit Rational -> Rectangle -> (Rectangle, Rectangle)
    forall r. RealFrac r => r -> Rectangle -> (Rectangle, Rectangle)
    splitVerticallyBy
            trySplit :: (Rational -> Rectangle -> (Rectangle, Rectangle))
    -> (Double, [(Window, Rectangle)])
    trySplit splitBy :: Rational -> Rectangle -> (Rectangle, Rectangle)
    splitBy =
                    (Double
    aBadness Double -> Double -> Double
    forall a. Num a => a -> a -> a
    + Double
    bBadness, [(Window, Rectangle)]
    aList [(Window, Rectangle)]
    -> [(Window, Rectangle)] -> [(Window, Rectangle)]
    forall a. [a] -> [a] -> [a]
    ++ [(Window, Rectangle)]
    bList)
                where
                    (aBadness :: Double
    aBadness, aList :: [(Window, Rectangle)]
    aList) = Int
    -> Rectangle -> Tree -> Params -> (Double, [(Window, Rectangle)])
    findSplits (Int
    depth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1) Rectangle
    aRect Tree
    aTree Params
    params
                    (bBadness :: Double
    bBadness, bList :: [(Window, Rectangle)]
    bList) = Int
    -> Rectangle -> Tree -> Params -> (Double, [(Window, Rectangle)])
    findSplits (Int
    depth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1) Rectangle
    bRect Tree
    bTree Params
    params
                    (aRect :: Rectangle
    aRect, bRect :: Rectangle
    bRect) = Rational -> Rectangle -> (Rectangle, Rectangle)
    splitBy Rational
    ratio Rectangle
    rect
            ratio :: Rational
    ratio = Rational
    aArea Rational -> Rational -> Rational
    forall a. Fractional a => a -> a -> a
    / (Rational
    aArea Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    + Rational
    bArea)

    -- Decide how much we like this rectangle.
    aspectBadness :: Rectangle -> Window -> Params -> Double
    aspectBadness :: Rectangle -> Window -> Params -> Double
    aspectBadness rect :: Rectangle
    rect win :: Window
    win params :: Params
    params =
            (if Double
    a Double -> Double -> Bool
    forall a. Ord a => a -> a -> Bool
    < 1 then Double
    tall else Double
    wide) Double -> Double -> Double
    forall a. Num a => a -> a -> a
    * Double -> Double
    forall a. Floating a => a -> a
    sqrt(Double
    w Double -> Double -> Double
    forall a. Num a => a -> a -> a
    * Double
    h)
        where
            tall :: Double
    tall = if Double
    w Double -> Double -> Bool
    forall a. Ord a => a -> a -> Bool
    < 700 then ((1 Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / Double
    a) Double -> Double -> Double
    forall a. Num a => a -> a -> a
    * (700 Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / Double
    w)) else 1 Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / Double
    a
            wide :: Double
    wide = if Double
    w Double -> Double -> Bool
    forall a. Ord a => a -> a -> Bool
    < 700 then Double
    a else (Double
    a Double -> Double -> Double
    forall a. Num a => a -> a -> a
    * Double
    w Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / 700)
            a :: Double
    a = (Double
    w Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / Double
    h) Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / Rational -> Double
    forall a. Fractional a => Rational -> a
    fromRational (Rational -> (Param -> Rational) -> Maybe Param -> Rational
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe 1.5 Param -> Rational
    aspect (Maybe Param -> Rational) -> Maybe Param -> Rational
    forall a b. (a -> b) -> a -> b
    $ Window -> Params -> Maybe Param
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup Window
    win Params
    params)
            w :: Double
    w = Dimension -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension -> Double) -> Dimension -> Double
    forall a b. (a -> b) -> a -> b
    $ Rectangle -> Dimension
    rect_width Rectangle
    rect
            h :: Double
    h = Dimension -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension -> Double) -> Dimension -> Double
    forall a b. (a -> b) -> a -> b
    $ Rectangle -> Dimension
    rect_height Rectangle
    rect

    -- vim: sw=4:et