    {-# LANGUAGE DeriveDataTypeable    #-}
    {-# LANGUAGE FlexibleContexts      #-}
    {-# LANGUAGE FlexibleInstances     #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE PatternGuards         #-}
    {-# LANGUAGE RecordWildCards       #-}
    {-# LANGUAGE UndecidableInstances  #-}
    {-# LANGUAGE ScopedTypeVariables   #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Layout.LayoutBuilder
    --
    -- Copyright   :  (c) 2009 Anders Engstrom <ankaan@gmail.com>,
    --                    2011 Ilya Portnov <portnov84@rambler.ru>,
    --                    2015 Peter Jones <pjones@devalot.com>
    --
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  Anders Engstrom <ankaan@gmail.com>,
    --                Ilya Portnov <portnov84@rambler.ru>,
    --                Peter Jones <pjones@devalot.com>
    --
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- A layout combinator that sends a specified number of windows to one rectangle
    -- and the rest to another. Each of these rectangles are given a layout that
    -- is used within them. This can be chained to provide an arbitrary number of
    -- rectangles. The layout combinator allows overlapping rectangles, but such
    -- layouts does not work well together with hinting
    -- ("XMonad.Layout.LayoutHints", "XMonad.Layout.HintedGrid" etc.)
    --
    -----------------------------------------------------------------------------
    module XMonad.Layout.LayoutBuilder (
      -- * Usage
      -- $usage
      layoutN,
      layoutR,
      layoutP,
      layoutAll,

      -- * Selecting Windows
      -- $selectWin
      Predicate (..),
      Proxy(..),

      -- * Messages
      IncLayoutN (..),

      -- * Utilities
      SubMeasure (..),
      SubBox (..),
      absBox,
      relBox,
      LayoutB,
      LayoutN,
    ) where

    --------------------------------------------------------------------------------
    import Control.Applicative ((<|>))
    import Control.Monad (foldM)
    import Data.Maybe
    import XMonad
    import qualified XMonad.StackSet as W
    import XMonad.Util.WindowProperties

    --------------------------------------------------------------------------------
    -- $usage
    -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
    --
    -- > import XMonad.Layout.LayoutBuilder
    --
    -- Then edit your @layoutHook@ by adding something like:
    --
    -- > myLayout = ( (layoutN 1 (relBox 0 0 0.5 1) (Just $ relBox 0 0 1 1) $ simpleTabbed)
    -- >             $ (layoutAll (relBox 0.5 0 1 1)                         $ simpleTabbed)
    -- >             ) |||
    -- >             ( (layoutN 1       (relBox (1/3) 0 (1/2) 1) (Just $ relBox 0 0 1 1) $ Tall 0 0.01 0.5)
    -- >             $ (layoutR 0.1 0.5 (relBox (2/3) 0 1     1) Nothing                 $ Tall 0 0.01 0.5)
    -- >             $ (layoutAll       (relBox 0     0 (1/3) 1)                         $ Tall 0 0.01 0.5)
    -- >             ) |||
    -- >             ( (layoutN 1 (absBox (-512-200) 0 512        0) (Just $ relBox 0 0 1 1) $ simpleTabbed)
    -- >             $ (layoutN 1 (absBox (-200)     0 0          0) Nothing                 $ simpleTabbed)
    -- >             $ (layoutAll (absBox 0          0 (-512-200) 0)                         $ simpleTabbed)
    -- >             ) |||
    -- >             ( (layoutN 1 (absBox 10 0 0 (-10)) Nothing $ Tall 0 0.01 0.5)
    -- >             $ (layoutN 1 (absBox 0 0 200 0) Nothing $ Tall 0 0.01 0.5)
    -- >             $ (layoutAll (absBox 10 10 0 0) $ Tall 2 0.01 0.5)
    -- >             ) ||| Full ||| etc...
    -- > main = xmonad def { layoutHook = myLayout }
    --
    -- This will produce a layout similar to DragPane, but with the possibility to have multiple windows in the left half
    -- and tabs that show the available windows. It will also produce a layout similar to ThreeColMid and a special layout
    -- created for use with a 80 columns wide Emacs window, its sidebar and a tabbed area for all other windows.
    --
    -- The final layout is for applications that use a toolbar in a separate window, shown on a low resolution screen. It has
    -- a master area that cover almost the whole screen. It leaves 10 px to the left and 10 px at the bottom. To the left
    -- the toolbar is located and can be accessed by focusing this area. It is actually 200 px wide, but usually below the
    -- other windows. Similarly all other windows are tiled, but behind the master window and can be accessed by moving the
    -- mouse to the bottom of the screen. Everything can also be accessed by the standard focus changing key bindings.
    --
    -- This module can be used to create many different custom layouts, but there are limitations. The primary limitation
    -- can be observed in the second and third example when there are only two columns with windows in them. The leftmost
    -- area is left blank. These blank areas can be avoided by placing the rectangles appropriately.
    --
    -- These examples require "XMonad.Layout.Tabbed".
    --
    -- For more detailed instructions on editing the layoutHook see:
    --
    -- "XMonad.Doc.Extending#Editing_the_layout_hook"
    --
    -- You may wish to add the following keybindings:
    --
    -- >    , ((modm .|. shiftMask, xK_h ), sendMessage $ IncLayoutN (-1))
    -- >    , ((modm .|. shiftMask, xK_l ), sendMessage $ IncLayoutN 1)
    --
    -- For detailed instruction on editing the key binding see:
    --
    -- "XMonad.Doc.Extending#Editing_key_bindings".

    --------------------------------------------------------------------------------
    -- $selectWin
    --
    -- 'Predicate' exists because layouts are required to be serializable, and
    -- "XMonad.Util.WindowProperties" is not sufficient (for example it does not
    -- allow using regular expressions).
    --
    -- compare "XMonad.Util.Invisible"

    -- | Type class for predicates. This enables us to manage not only Windows,
    -- but any objects, for which instance Predicate is defined.
    --
    -- Another instance exists in XMonad.Util.WindowPropertiesRE in xmonad-extras
    class Predicate p w where
      alwaysTrue     :: Proxy w -> p     -- ^ A predicate that is always True.
      checkPredicate :: p -> w -> X Bool -- ^ Check if given object (window or smth else) matches that predicate

    instance Predicate () a where
      alwaysTrue :: Proxy a -> ()
    alwaysTrue _       = ()
      checkPredicate :: () -> a -> X Bool
    checkPredicate _ _ = Bool -> X Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    True

    instance Predicate Property Window where
      alwaysTrue :: Proxy Window -> Property
    alwaysTrue _   = Bool -> Property
    Const Bool
    True
      checkPredicate :: Property -> Window -> X Bool
    checkPredicate = Property -> Window -> X Bool
    hasProperty

    --------------------------------------------------------------------------------
    -- | Contains no actual data, but is needed to help select the correct instance
    -- of 'Predicate'
    data Proxy a = Proxy

    --------------------------------------------------------------------------------
    -- | Information about how to split windows between layouts.
    data Limit p = LimitN Int                  -- ^ See: 'layoutN'.
                 | LimitR (Rational, Rational) -- ^ See: 'layoutR'.
                 | LimitP p                    -- ^ See: 'layoutP'.
                 deriving (Int -> Limit p -> ShowS
    [Limit p] -> ShowS
    Limit p -> String
    (Int -> Limit p -> ShowS)
    -> (Limit p -> String) -> ([Limit p] -> ShowS) -> Show (Limit p)
    forall p. Show p => Int -> Limit p -> ShowS
    forall p. Show p => [Limit p] -> ShowS
    forall p. Show p => Limit p -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [Limit p] -> ShowS
    $cshowList :: forall p. Show p => [Limit p] -> ShowS
    show :: Limit p -> String
    $cshow :: forall p. Show p => Limit p -> String
    showsPrec :: Int -> Limit p -> ShowS
    $cshowsPrec :: forall p. Show p => Int -> Limit p -> ShowS
    Show, ReadPrec [Limit p]
    ReadPrec (Limit p)
    Int -> ReadS (Limit p)
    ReadS [Limit p]
    (Int -> ReadS (Limit p))
    -> ReadS [Limit p]
    -> ReadPrec (Limit p)
    -> ReadPrec [Limit p]
    -> Read (Limit p)
    forall p. Read p => ReadPrec [Limit p]
    forall p. Read p => ReadPrec (Limit p)
    forall p. Read p => Int -> ReadS (Limit p)
    forall p. Read p => ReadS [Limit p]
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    readListPrec :: ReadPrec [Limit p]
    $creadListPrec :: forall p. Read p => ReadPrec [Limit p]
    readPrec :: ReadPrec (Limit p)
    $creadPrec :: forall p. Read p => ReadPrec (Limit p)
    readList :: ReadS [Limit p]
    $creadList :: forall p. Read p => ReadS [Limit p]
    readsPrec :: Int -> ReadS (Limit p)
    $creadsPrec :: forall p. Read p => Int -> ReadS (Limit p)
    Read)

    --------------------------------------------------------------------------------
    -- | Use one layout in the specified area for a number of windows and
    -- possibly let another layout handle the rest.
    data LayoutB l1 l2 p a = LayoutB
        { LayoutB l1 l2 p a -> Maybe a
    subFocus  :: Maybe a      -- ^ The focused window in this layout.
        , LayoutB l1 l2 p a -> Maybe a
    nextFocus :: Maybe a      -- ^ The focused window in the next layout.
        , LayoutB l1 l2 p a -> Limit p
    limit     :: Limit p      -- ^ How to split windows between layouts.
        , LayoutB l1 l2 p a -> SubBox
    box       :: SubBox       -- ^ Normal size of layout.
        , LayoutB l1 l2 p a -> Maybe SubBox
    mbox      :: Maybe SubBox -- ^ Size of layout when handling all windows.
        , LayoutB l1 l2 p a -> l1 a
    sub       :: l1 a         -- ^ The layout to use in this box.
        , LayoutB l1 l2 p a -> Maybe (l2 a)
    next      :: Maybe (l2 a) -- ^ The next layout in the chain.
        } deriving (Int -> LayoutB l1 l2 p a -> ShowS
    [LayoutB l1 l2 p a] -> ShowS
    LayoutB l1 l2 p a -> String
    (Int -> LayoutB l1 l2 p a -> ShowS)
    -> (LayoutB l1 l2 p a -> String)
    -> ([LayoutB l1 l2 p a] -> ShowS)
    -> Show (LayoutB l1 l2 p a)
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Show a, Show p, Show (l1 a), Show (l2 a)) =>
    Int -> LayoutB l1 l2 p a -> ShowS
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Show a, Show p, Show (l1 a), Show (l2 a)) =>
    [LayoutB l1 l2 p a] -> ShowS
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Show a, Show p, Show (l1 a), Show (l2 a)) =>
    LayoutB l1 l2 p a -> String
    showList :: [LayoutB l1 l2 p a] -> ShowS
    $cshowList :: forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Show a, Show p, Show (l1 a), Show (l2 a)) =>
    [LayoutB l1 l2 p a] -> ShowS
    show :: LayoutB l1 l2 p a -> String
    $cshow :: forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Show a, Show p, Show (l1 a), Show (l2 a)) =>
    LayoutB l1 l2 p a -> String
    showsPrec :: Int -> LayoutB l1 l2 p a -> ShowS
    $cshowsPrec :: forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Show a, Show p, Show (l1 a), Show (l2 a)) =>
    Int -> LayoutB l1 l2 p a -> ShowS
    Show, ReadPrec [LayoutB l1 l2 p a]
    ReadPrec (LayoutB l1 l2 p a)
    Int -> ReadS (LayoutB l1 l2 p a)
    ReadS [LayoutB l1 l2 p a]
    (Int -> ReadS (LayoutB l1 l2 p a))
    -> ReadS [LayoutB l1 l2 p a]
    -> ReadPrec (LayoutB l1 l2 p a)
    -> ReadPrec [LayoutB l1 l2 p a]
    -> Read (LayoutB l1 l2 p a)
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Read a, Read p, Read (l1 a), Read (l2 a)) =>
    ReadPrec [LayoutB l1 l2 p a]
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Read a, Read p, Read (l1 a), Read (l2 a)) =>
    ReadPrec (LayoutB l1 l2 p a)
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Read a, Read p, Read (l1 a), Read (l2 a)) =>
    Int -> ReadS (LayoutB l1 l2 p a)
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Read a, Read p, Read (l1 a), Read (l2 a)) =>
    ReadS [LayoutB l1 l2 p a]
    readListPrec :: ReadPrec [LayoutB l1 l2 p a]
    $creadListPrec :: forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Read a, Read p, Read (l1 a), Read (l2 a)) =>
    ReadPrec [LayoutB l1 l2 p a]
    readPrec :: ReadPrec (LayoutB l1 l2 p a)
    $creadPrec :: forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Read a, Read p, Read (l1 a), Read (l2 a)) =>
    ReadPrec (LayoutB l1 l2 p a)
    readList :: ReadS [LayoutB l1 l2 p a]
    $creadList :: forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Read a, Read p, Read (l1 a), Read (l2 a)) =>
    ReadS [LayoutB l1 l2 p a]
    readsPrec :: Int -> ReadS (LayoutB l1 l2 p a)
    $creadsPrec :: forall (l1 :: * -> *) (l2 :: * -> *) p a.
    (Read a, Read p, Read (l1 a), Read (l2 a)) =>
    Int -> ReadS (LayoutB l1 l2 p a)
    Read)

    --------------------------------------------------------------------------------
    -- | A variant of 'LayoutB' that can't use 'layoutP'.  For backwards
    -- compatibility with previous versions of LayoutBuilder.
    type LayoutN l1 l2 a = LayoutB l1 l2 () a

    --------------------------------------------------------------------------------
    -- | Use the specified layout in the described area for N windows and
    -- send the rest of the windows to the next layout in the chain.  It
    -- is possible to supply an alternative area that will then be used
    -- instead, if there are no windows to send to the next layout.
    layoutN :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) =>
           Int                               -- ^ The number of windows to handle
        -> SubBox                            -- ^ The box to place the windows in
        -> Maybe SubBox                      -- ^ Possibly an alternative box that is used when this layout handles all windows that are left
        -> l1 a                              -- ^ The layout to use in the specified area
        -> LayoutB l2 l3 p a                 -- ^ Where to send the remaining windows
        -> LayoutB l1 (LayoutB l2 l3 p) () a -- ^ The resulting layout
    layoutN :: Int
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> LayoutB l2 l3 p a
    -> LayoutB l1 (LayoutB l2 l3 p) () a
    layoutN num :: Int
    num box :: SubBox
    box mbox :: Maybe SubBox
    mbox sub :: l1 a
    sub next :: LayoutB l2 l3 p a
    next = Maybe a
    -> Maybe a
    -> Limit ()
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (LayoutB l2 l3 p a)
    -> LayoutB l1 (LayoutB l2 l3 p) () a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    LayoutB Maybe a
    forall a. Maybe a
    Nothing Maybe a
    forall a. Maybe a
    Nothing (Int -> Limit ()
    forall p. Int -> Limit p
    LimitN Int
    num) SubBox
    box Maybe SubBox
    mbox l1 a
    sub (LayoutB l2 l3 p a -> Maybe (LayoutB l2 l3 p a)
    forall a. a -> Maybe a
    Just LayoutB l2 l3 p a
    next)

    -- | As layoutN, but the number of windows is given relative to the total number of windows remaining to be handled. The first
    --   argument is how much to change the ratio when using IncLayoutN, and the second is the initial ratio.
    layoutR :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) =>
           Rational                         -- ^ How much to change the ratio with each IncLayoutN
        -> Rational                         -- ^ The ratio of the remaining windows to handle
        -> SubBox                           -- ^ The box to place the windows in
        -> Maybe SubBox                     -- ^ Possibly an alternative box that is used when this layout handles all windows that are left
        -> l1 a                             -- ^ The layout to use in the specified area
        -> LayoutB l2 l3 p a                -- ^ Where to send the remaining windows
        -> LayoutB l1 (LayoutB l2 l3 p) p a -- ^ The resulting layout
    layoutR :: Rational
    -> Rational
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> LayoutB l2 l3 p a
    -> LayoutB l1 (LayoutB l2 l3 p) p a
    layoutR numdiff :: Rational
    numdiff num :: Rational
    num box :: SubBox
    box mbox :: Maybe SubBox
    mbox sub :: l1 a
    sub next :: LayoutB l2 l3 p a
    next = Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (LayoutB l2 l3 p a)
    -> LayoutB l1 (LayoutB l2 l3 p) p a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    LayoutB Maybe a
    forall a. Maybe a
    Nothing Maybe a
    forall a. Maybe a
    Nothing ((Rational, Rational) -> Limit p
    forall p. (Rational, Rational) -> Limit p
    LimitR (Rational
    numdiff,Rational
    num)) SubBox
    box Maybe SubBox
    mbox l1 a
    sub (LayoutB l2 l3 p a -> Maybe (LayoutB l2 l3 p a)
    forall a. a -> Maybe a
    Just LayoutB l2 l3 p a
    next)

    --------------------------------------------------------------------------------
    -- | Use the specified layout in the described area windows that match
    -- given predicate and send the rest of the windows to the next layout
    -- in the chain.  It is possible to supply an alternative area that
    -- will then be used instead, if there are no windows to send to the
    -- next layout.
    layoutP :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a, Predicate p a, Predicate p' a) =>
           p                                 -- ^ The predicate to use
        -> SubBox                            -- ^ The box to place the windows in
        -> Maybe SubBox                      -- ^ Possibly an alternative box that is used when this layout handles all windows that are left
        -> l1 a                              -- ^ The layout to use in the specified area
        -> LayoutB l2 l3 p' a                -- ^ Where to send the remaining windows
        -> LayoutB l1 (LayoutB l2 l3 p') p a -- ^ The resulting layout
    layoutP :: p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> LayoutB l2 l3 p' a
    -> LayoutB l1 (LayoutB l2 l3 p') p a
    layoutP prop :: p
    prop box :: SubBox
    box mbox :: Maybe SubBox
    mbox sub :: l1 a
    sub next :: LayoutB l2 l3 p' a
    next = Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (LayoutB l2 l3 p' a)
    -> LayoutB l1 (LayoutB l2 l3 p') p a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    LayoutB Maybe a
    forall a. Maybe a
    Nothing Maybe a
    forall a. Maybe a
    Nothing (p -> Limit p
    forall p. p -> Limit p
    LimitP p
    prop) SubBox
    box Maybe SubBox
    mbox l1 a
    sub (LayoutB l2 l3 p' a -> Maybe (LayoutB l2 l3 p' a)
    forall a. a -> Maybe a
    Just LayoutB l2 l3 p' a
    next)

    --------------------------------------------------------------------------------
    -- | Use the specified layout in the described area for all remaining windows.
    layoutAll :: (Read a, Eq a, LayoutClass l1 a) =>
           SubBox                -- ^ The box to place the windows in
        -> l1 a                  -- ^ The layout to use in the specified area
        -> LayoutB l1 Full () a  -- ^ The resulting layout
    layoutAll :: SubBox -> l1 a -> LayoutB l1 Full () a
    layoutAll box :: SubBox
    box sub :: l1 a
    sub = Maybe a
    -> Maybe a
    -> Limit ()
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (Full a)
    -> LayoutB l1 Full () a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    LayoutB Maybe a
    forall a. Maybe a
    Nothing Maybe a
    forall a. Maybe a
    Nothing ((Rational, Rational) -> Limit ()
    forall p. (Rational, Rational) -> Limit p
    LimitR (0,1)) SubBox
    box Maybe SubBox
    forall a. Maybe a
    Nothing l1 a
    sub Maybe (Full a)
    forall a. Maybe a
    Nothing

    --------------------------------------------------------------------------------
    -- | Change the number of windows handled by the focused layout.
    data IncLayoutN = IncLayoutN Int deriving Typeable
    instance Message IncLayoutN

    --------------------------------------------------------------------------------
    -- | The absolute or relative measures used to describe the area a layout should be placed in. For negative absolute values
    --   the total remaining space will be added. For sizes, the remaining space will also be added for zeroes. Relative values
    --   are applied on the remaining space after the top-left corner of the box have been removed.
    data SubMeasure = Abs Int | Rel Rational deriving (Int -> SubMeasure -> ShowS
    [SubMeasure] -> ShowS
    SubMeasure -> String
    (Int -> SubMeasure -> ShowS)
    -> (SubMeasure -> String)
    -> ([SubMeasure] -> ShowS)
    -> Show SubMeasure
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [SubMeasure] -> ShowS
    $cshowList :: [SubMeasure] -> ShowS
    show :: SubMeasure -> String
    $cshow :: SubMeasure -> String
    showsPrec :: Int -> SubMeasure -> ShowS
    $cshowsPrec :: Int -> SubMeasure -> ShowS
    Show,ReadPrec [SubMeasure]
    ReadPrec SubMeasure
    Int -> ReadS SubMeasure
    ReadS [SubMeasure]
    (Int -> ReadS SubMeasure)
    -> ReadS [SubMeasure]
    -> ReadPrec SubMeasure
    -> ReadPrec [SubMeasure]
    -> Read SubMeasure
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    readListPrec :: ReadPrec [SubMeasure]
    $creadListPrec :: ReadPrec [SubMeasure]
    readPrec :: ReadPrec SubMeasure
    $creadPrec :: ReadPrec SubMeasure
    readList :: ReadS [SubMeasure]
    $creadList :: ReadS [SubMeasure]
    readsPrec :: Int -> ReadS SubMeasure
    $creadsPrec :: Int -> ReadS SubMeasure
    Read)

    --------------------------------------------------------------------------------
    -- | A box to place a layout in. The stored values are xpos, ypos, width and height.
    data SubBox = SubBox SubMeasure SubMeasure SubMeasure SubMeasure deriving (Int -> SubBox -> ShowS
    [SubBox] -> ShowS
    SubBox -> String
    (Int -> SubBox -> ShowS)
    -> (SubBox -> String) -> ([SubBox] -> ShowS) -> Show SubBox
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [SubBox] -> ShowS
    $cshowList :: [SubBox] -> ShowS
    show :: SubBox -> String
    $cshow :: SubBox -> String
    showsPrec :: Int -> SubBox -> ShowS
    $cshowsPrec :: Int -> SubBox -> ShowS
    Show,ReadPrec [SubBox]
    ReadPrec SubBox
    Int -> ReadS SubBox
    ReadS [SubBox]
    (Int -> ReadS SubBox)
    -> ReadS [SubBox]
    -> ReadPrec SubBox
    -> ReadPrec [SubBox]
    -> Read SubBox
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    readListPrec :: ReadPrec [SubBox]
    $creadListPrec :: ReadPrec [SubBox]
    readPrec :: ReadPrec SubBox
    $creadPrec :: ReadPrec SubBox
    readList :: ReadS [SubBox]
    $creadList :: ReadS [SubBox]
    readsPrec :: Int -> ReadS SubBox
    $creadsPrec :: Int -> ReadS SubBox
    Read)

    --------------------------------------------------------------------------------
    -- | Create a box with only absolute measurements. If the values are negative, the total remaining space will be added. For
    --   sizes it will also be added for zeroes.
    absBox :: Int     -- ^ Absolute X-Position
           -> Int     -- ^ Absolute Y-Position
           -> Int     -- ^ Absolute width
           -> Int     -- ^ Absolute height
           -> SubBox  -- ^ The resulting 'SubBox' describing the area
    absBox :: Int -> Int -> Int -> Int -> SubBox
    absBox x :: Int
    x y :: Int
    y w :: Int
    w h :: Int
    h = SubMeasure -> SubMeasure -> SubMeasure -> SubMeasure -> SubBox
    SubBox (Int -> SubMeasure
    Abs Int
    x) (Int -> SubMeasure
    Abs Int
    y) (Int -> SubMeasure
    Abs Int
    w) (Int -> SubMeasure
    Abs Int
    h)

    --------------------------------------------------------------------------------
    -- | Create a box with only relative measurements.
    relBox :: Rational  -- ^ Relative X-Position with respect to the surrounding area
           -> Rational  -- ^ Relative Y-Position with respect to the surrounding area
           -> Rational  -- ^ Relative width with respect to the remaining width
           -> Rational  -- ^ Relative height with respect to the remaining height
           -> SubBox    -- ^ The resulting 'SubBox' describing the area
    relBox :: Rational -> Rational -> Rational -> Rational -> SubBox
    relBox x :: Rational
    x y :: Rational
    y w :: Rational
    w h :: Rational
    h = SubMeasure -> SubMeasure -> SubMeasure -> SubMeasure -> SubBox
    SubBox (Rational -> SubMeasure
    Rel Rational
    x) (Rational -> SubMeasure
    Rel Rational
    y) (Rational -> SubMeasure
    Rel Rational
    w) (Rational -> SubMeasure
    Rel Rational
    h)

    --------------------------------------------------------------------------------
    instance ( LayoutClass l1 a, LayoutClass l2 a
             , Read a, Show a, Show p, Eq a, Typeable a, Predicate p a
             ) => LayoutClass (LayoutB l1 l2 p) a where

        -- | Update window locations.
        runLayout :: Workspace String (LayoutB l1 l2 p a) a
    -> Rectangle -> X ([(a, Rectangle)], Maybe (LayoutB l1 l2 p a))
    runLayout (W.Workspace _ LayoutB {..} s :: Maybe (Stack a)
    s) rect :: Rectangle
    rect = do
            (subs :: Maybe (Stack a)
    subs, nexts :: Maybe (Stack a)
    nexts, subFocus' :: Maybe a
    subFocus', nextFocus' :: Maybe a
    nextFocus') <- Maybe (Stack a)
    -> Limit p
    -> Maybe a
    -> Maybe a
    -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    forall a p.
    (Eq a, Predicate p a) =>
    Maybe (Stack a)
    -> Limit p
    -> Maybe a
    -> Maybe a
    -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    splitStack Maybe (Stack a)
    s Limit p
    limit Maybe a
    subFocus Maybe a
    nextFocus

            let selBox :: SubBox
    selBox = if Maybe a -> Bool
    forall a. Maybe a -> Bool
    isJust Maybe a
    nextFocus' then SubBox
    box else SubBox -> Maybe SubBox -> SubBox
    forall a. a -> Maybe a -> a
    fromMaybe SubBox
    box Maybe SubBox
    mbox

            (sublist :: [(a, Rectangle)]
    sublist, sub' :: l1 a
    sub', schange :: Bool
    schange) <- l1 a
    -> Maybe (Stack a) -> Rectangle -> X ([(a, Rectangle)], l1 a, Bool)
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a
    -> Maybe (Stack a)
    -> Rectangle
    -> X ([(a, Rectangle)], layout a, Bool)
    handle l1 a
    sub Maybe (Stack a)
    subs (SubBox -> Rectangle -> Rectangle
    calcArea SubBox
    selBox Rectangle
    rect)

            (nextlist :: [(a, Rectangle)]
    nextlist, next' :: Maybe (l2 a)
    next', nchange :: Bool
    nchange) <- case Maybe (l2 a)
    next of
              Nothing -> ([(a, Rectangle)], Maybe (l2 a), Bool)
    -> X ([(a, Rectangle)], Maybe (l2 a), Bool)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([], Maybe (l2 a)
    forall a. Maybe a
    Nothing, Bool
    False)
              Just n :: l2 a
    n  -> do (res :: [(a, Rectangle)]
    res, l :: l2 a
    l, ch :: Bool
    ch) <- l2 a
    -> Maybe (Stack a) -> Rectangle -> X ([(a, Rectangle)], l2 a, Bool)
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a
    -> Maybe (Stack a)
    -> Rectangle
    -> X ([(a, Rectangle)], layout a, Bool)
    handle l2 a
    n Maybe (Stack a)
    nexts Rectangle
    rect
                            ([(a, Rectangle)], Maybe (l2 a), Bool)
    -> X ([(a, Rectangle)], Maybe (l2 a), Bool)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(a, Rectangle)]
    res, l2 a -> Maybe (l2 a)
    forall a. a -> Maybe a
    Just l2 a
    l, Bool
    ch)

            let newlist :: [(a, Rectangle)]
    newlist =  if [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length ([a] -> (Stack a -> [a]) -> Maybe (Stack a) -> [a]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [] Stack a -> [a]
    forall a. Stack a -> [a]
    W.up Maybe (Stack a)
    s) Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length (Maybe (Stack a) -> [a]
    forall a. Maybe (Stack a) -> [a]
    W.integrate' Maybe (Stack a)
    subs)
                             then [(a, Rectangle)]
    sublist[(a, Rectangle)] -> [(a, Rectangle)] -> [(a, Rectangle)]
    forall a. [a] -> [a] -> [a]
    ++[(a, Rectangle)]
    nextlist
                             else [(a, Rectangle)]
    nextlist[(a, Rectangle)] -> [(a, Rectangle)] -> [(a, Rectangle)]
    forall a. [a] -> [a] -> [a]
    ++[(a, Rectangle)]
    sublist

                newstate :: Maybe (LayoutB l1 l2 p a)
    newstate = if Maybe a
    subFocus' Maybe a -> Maybe a -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Maybe a
    subFocus Bool -> Bool -> Bool
    || Maybe a
    nextFocus' Maybe a -> Maybe a -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Maybe a
    nextFocus Bool -> Bool -> Bool
    || Bool
    schange Bool -> Bool -> Bool
    || Bool
    nchange
                             then LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a)
    forall a. a -> Maybe a
    Just (LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a))
    -> LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a)
    forall a b. (a -> b) -> a -> b
    $ Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    LayoutB Maybe a
    subFocus' Maybe a
    nextFocus' Limit p
    limit SubBox
    box Maybe SubBox
    mbox l1 a
    sub' Maybe (l2 a)
    next'
                             else Maybe (LayoutB l1 l2 p a)
    forall a. Maybe a
    Nothing

            ([(a, Rectangle)], Maybe (LayoutB l1 l2 p a))
    -> X ([(a, Rectangle)], Maybe (LayoutB l1 l2 p a))
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(a, Rectangle)]
    newlist, Maybe (LayoutB l1 l2 p a)
    newstate)
          where
              handle :: layout a
    -> Maybe (Stack a)
    -> Rectangle
    -> X ([(a, Rectangle)], layout a, Bool)
    handle l :: layout a
    l s' :: Maybe (Stack a)
    s' r :: Rectangle
    r = do (res :: [(a, Rectangle)]
    res,ml :: Maybe (layout a)
    ml) <- Workspace String (layout a) a
    -> Rectangle -> X ([(a, Rectangle)], Maybe (layout a))
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    Workspace String (layout a) a
    -> Rectangle -> X ([(a, Rectangle)], Maybe (layout a))
    runLayout (String
    -> layout a -> Maybe (Stack a) -> Workspace String (layout a) a
    forall i l a. i -> l -> Maybe (Stack a) -> Workspace i l a
    W.Workspace "" layout a
    l Maybe (Stack a)
    s') Rectangle
    r
                                 ([(a, Rectangle)], layout a, Bool)
    -> X ([(a, Rectangle)], layout a, Bool)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(a, Rectangle)]
    res, layout a -> Maybe (layout a) -> layout a
    forall a. a -> Maybe a -> a
    fromMaybe layout a
    l Maybe (layout a)
    ml, Maybe (layout a) -> Bool
    forall a. Maybe a -> Bool
    isNothing Maybe (layout a)
    ml)

        -- |  Propagate messages.
        handleMessage :: LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    handleMessage l :: LayoutB l1 l2 p a
    l m :: SomeMessage
    m
            | Just (IncLayoutN n :: Int
    n) <- SomeMessage -> Maybe IncLayoutN
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    m = LayoutB l1 l2 p a
    -> SomeMessage -> Int -> X (Maybe (LayoutB l1 l2 p a))
    forall (l1 :: * -> *) a (l2 :: * -> *) p.
    (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a,
     Typeable a) =>
    LayoutB l1 l2 p a
    -> SomeMessage -> Int -> X (Maybe (LayoutB l1 l2 p a))
    incLayoutN LayoutB l1 l2 p a
    l SomeMessage
    m Int
    n
            | Just (IncMasterN _) <- SomeMessage -> Maybe IncMasterN
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    m = LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    forall (l1 :: * -> *) a (l2 :: * -> *) p.
    (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a,
     Typeable a) =>
    LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendFocus  LayoutB l1 l2 p a
    l SomeMessage
    m
            | Just Shrink         <- SomeMessage -> Maybe Resize
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    m = LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    forall (l1 :: * -> *) a (l2 :: * -> *) p.
    (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a,
     Typeable a) =>
    LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendFocus  LayoutB l1 l2 p a
    l SomeMessage
    m
            | Just Expand         <- SomeMessage -> Maybe Resize
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    m = LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    forall (l1 :: * -> *) a (l2 :: * -> *) p.
    (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a,
     Typeable a) =>
    LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendFocus  LayoutB l1 l2 p a
    l SomeMessage
    m
            | Bool
    otherwise                            = LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    forall (l1 :: * -> *) a (l2 :: * -> *) p.
    (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a,
     Typeable a) =>
    LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendBoth   LayoutB l1 l2 p a
    l SomeMessage
    m

        -- | Descriptive name for layout.
        description :: LayoutB l1 l2 p a -> String
    description layout :: LayoutB l1 l2 p a
    layout = case LayoutB l1 l2 p a
    layout of
            (LayoutB _ _ _ _ _ sub :: l1 a
    sub Nothing) ->
              "layoutAll " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ l1 a -> String
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> String
    description l1 a
    sub

            (LayoutB _ _ (LimitN _) _ _ sub :: l1 a
    sub (Just next :: l2 a
    next)) ->
              "layoutN " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ l1 a -> String
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> String
    description l1 a
    sub String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ " " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ l2 a -> String
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> String
    description l2 a
    next

            (LayoutB _ _ (LimitR _) _ _ sub :: l1 a
    sub (Just next :: l2 a
    next)) ->
              "layoutR " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ l1 a -> String
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> String
    description l1 a
    sub String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ " " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ l2 a -> String
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> String
    description l2 a
    next

            (LayoutB _ _ (LimitP _) _ _ sub :: l1 a
    sub (Just next :: l2 a
    next)) ->
              "layoutP " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ l1 a -> String
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> String
    description l1 a
    sub String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ " " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ l2 a -> String
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> String
    description l2 a
    next

    --------------------------------------------------------------------------------
    -- | Increase the number of windows allowed in the focused layout.
    incLayoutN :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a)
               => LayoutB l1 l2 p a
               -> SomeMessage
               -> Int
               -> X (Maybe (LayoutB l1 l2 p a))
    incLayoutN :: LayoutB l1 l2 p a
    -> SomeMessage -> Int -> X (Maybe (LayoutB l1 l2 p a))
    incLayoutN layout :: LayoutB l1 l2 p a
    layout@LayoutB {..} message :: SomeMessage
    message n :: Int
    n = do
        Bool
    incThis <- Maybe a -> X Bool
    forall a. Show a => Maybe a -> X Bool
    isFocus Maybe a
    subFocus

        if Bool
    incThis
           then Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a)))
    -> Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a))
    forall a b. (a -> b) -> a -> b
    $ LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a)
    forall a. a -> Maybe a
    Just LayoutB l1 l2 p a
    layout { limit :: Limit p
    limit = Limit p
    newLimit }
           else LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    forall (l1 :: * -> *) a (l2 :: * -> *) p.
    (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a,
     Typeable a) =>
    LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendNext LayoutB l1 l2 p a
    layout SomeMessage
    message

      where
        newLimit :: Limit p
    newLimit = case Limit p
    limit of
          LimitN oldnum :: Int
    oldnum         -> Int -> Limit p
    forall p. Int -> Limit p
    LimitN (Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max 1 (Int -> Int) -> Int -> Int
    forall a b. (a -> b) -> a -> b
    $ Int
    oldnum Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    n)
          LimitR (diff :: Rational
    diff, oldnum :: Rational
    oldnum) -> (Rational, Rational) -> Limit p
    forall p. (Rational, Rational) -> Limit p
    LimitR (Rational
    diff, Rational -> Rational -> Rational
    forall a. Ord a => a -> a -> a
    min 1 (Rational -> Rational) -> Rational -> Rational
    forall a b. (a -> b) -> a -> b
    $ Rational -> Rational -> Rational
    forall a. Ord a => a -> a -> a
    max 0 (Rational -> Rational) -> Rational -> Rational
    forall a b. (a -> b) -> a -> b
    $ Rational
    oldnum Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    + Int -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    n Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Rational
    diff)
          LimitP _              -> Limit p
    limit

    --------------------------------------------------------------------------------
    sendSub :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendSub :: LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendSub (LayoutB subFocus :: Maybe a
    subFocus nextFocus :: Maybe a
    nextFocus num :: Limit p
    num box :: SubBox
    box mbox :: Maybe SubBox
    mbox sub :: l1 a
    sub next :: Maybe (l2 a)
    next) m :: SomeMessage
    m =
        do Maybe (l1 a)
    sub' <- l1 a -> SomeMessage -> X (Maybe (l1 a))
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> SomeMessage -> X (Maybe (layout a))
    handleMessage l1 a
    sub SomeMessage
    m
           Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a)))
    -> Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a))
    forall a b. (a -> b) -> a -> b
    $ if Maybe (l1 a) -> Bool
    forall a. Maybe a -> Bool
    isJust Maybe (l1 a)
    sub'
                    then LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a)
    forall a. a -> Maybe a
    Just (LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a))
    -> LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a)
    forall a b. (a -> b) -> a -> b
    $ Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    LayoutB Maybe a
    subFocus Maybe a
    nextFocus Limit p
    num SubBox
    box Maybe SubBox
    mbox (l1 a -> Maybe (l1 a) -> l1 a
    forall a. a -> Maybe a -> a
    fromMaybe l1 a
    sub Maybe (l1 a)
    sub') Maybe (l2 a)
    next
                    else Maybe (LayoutB l1 l2 p a)
    forall a. Maybe a
    Nothing

    --------------------------------------------------------------------------------
    sendBoth :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendBoth :: LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendBoth l :: LayoutB l1 l2 p a
    l@(LayoutB _ _ _ _ _ _ Nothing) m :: SomeMessage
    m = LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    forall (l1 :: * -> *) a (l2 :: * -> *) p.
    (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a,
     Typeable a) =>
    LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendSub LayoutB l1 l2 p a
    l SomeMessage
    m
    sendBoth (LayoutB subFocus :: Maybe a
    subFocus nextFocus :: Maybe a
    nextFocus num :: Limit p
    num box :: SubBox
    box mbox :: Maybe SubBox
    mbox sub :: l1 a
    sub (Just next :: l2 a
    next)) m :: SomeMessage
    m =
        do Maybe (l1 a)
    sub' <- l1 a -> SomeMessage -> X (Maybe (l1 a))
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> SomeMessage -> X (Maybe (layout a))
    handleMessage l1 a
    sub SomeMessage
    m
           Maybe (l2 a)
    next' <- l2 a -> SomeMessage -> X (Maybe (l2 a))
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> SomeMessage -> X (Maybe (layout a))
    handleMessage l2 a
    next SomeMessage
    m
           Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a)))
    -> Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a))
    forall a b. (a -> b) -> a -> b
    $ if Maybe (l1 a) -> Bool
    forall a. Maybe a -> Bool
    isJust Maybe (l1 a)
    sub' Bool -> Bool -> Bool
    || Maybe (l2 a) -> Bool
    forall a. Maybe a -> Bool
    isJust Maybe (l2 a)
    next'
                    then LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a)
    forall a. a -> Maybe a
    Just (LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a))
    -> LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a)
    forall a b. (a -> b) -> a -> b
    $ Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    LayoutB Maybe a
    subFocus Maybe a
    nextFocus Limit p
    num SubBox
    box Maybe SubBox
    mbox (l1 a -> Maybe (l1 a) -> l1 a
    forall a. a -> Maybe a -> a
    fromMaybe l1 a
    sub Maybe (l1 a)
    sub') (Maybe (l2 a)
    next' Maybe (l2 a) -> Maybe (l2 a) -> Maybe (l2 a)
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> l2 a -> Maybe (l2 a)
    forall a. a -> Maybe a
    Just l2 a
    next)
                    else Maybe (LayoutB l1 l2 p a)
    forall a. Maybe a
    Nothing

    --------------------------------------------------------------------------------
    sendNext :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendNext :: LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendNext (LayoutB _ _ _ _ _ _ Nothing) _ = Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a))
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (LayoutB l1 l2 p a)
    forall a. Maybe a
    Nothing
    sendNext (LayoutB subFocus :: Maybe a
    subFocus nextFocus :: Maybe a
    nextFocus num :: Limit p
    num box :: SubBox
    box mbox :: Maybe SubBox
    mbox sub :: l1 a
    sub (Just next :: l2 a
    next)) m :: SomeMessage
    m =
        do Maybe (l2 a)
    next' <- l2 a -> SomeMessage -> X (Maybe (l2 a))
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    layout a -> SomeMessage -> X (Maybe (layout a))
    handleMessage l2 a
    next SomeMessage
    m
           Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a)))
    -> Maybe (LayoutB l1 l2 p a) -> X (Maybe (LayoutB l1 l2 p a))
    forall a b. (a -> b) -> a -> b
    $ if Maybe (l2 a) -> Bool
    forall a. Maybe a -> Bool
    isJust Maybe (l2 a)
    next'
                    then LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a)
    forall a. a -> Maybe a
    Just (LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a))
    -> LayoutB l1 l2 p a -> Maybe (LayoutB l1 l2 p a)
    forall a b. (a -> b) -> a -> b
    $ Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    forall (l1 :: * -> *) (l2 :: * -> *) p a.
    Maybe a
    -> Maybe a
    -> Limit p
    -> SubBox
    -> Maybe SubBox
    -> l1 a
    -> Maybe (l2 a)
    -> LayoutB l1 l2 p a
    LayoutB Maybe a
    subFocus Maybe a
    nextFocus Limit p
    num SubBox
    box Maybe SubBox
    mbox l1 a
    sub Maybe (l2 a)
    next'
                    else Maybe (LayoutB l1 l2 p a)
    forall a. Maybe a
    Nothing

    --------------------------------------------------------------------------------
    sendFocus :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendFocus :: LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendFocus l :: LayoutB l1 l2 p a
    l@(LayoutB subFocus :: Maybe a
    subFocus _ _ _ _ _ _) m :: SomeMessage
    m = do
      Bool
    foc <- Maybe a -> X Bool
    forall a. Show a => Maybe a -> X Bool
    isFocus Maybe a
    subFocus

      if Bool
    foc
        then LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    forall (l1 :: * -> *) a (l2 :: * -> *) p.
    (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a,
     Typeable a) =>
    LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendSub  LayoutB l1 l2 p a
    l SomeMessage
    m
        else LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    forall (l1 :: * -> *) a (l2 :: * -> *) p.
    (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a,
     Typeable a) =>
    LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
    sendNext LayoutB l1 l2 p a
    l SomeMessage
    m

    --------------------------------------------------------------------------------
    -- | Check to see if the given window is currently focused.
    isFocus :: (Show a) => Maybe a -> X Bool
    isFocus :: Maybe a -> X Bool
    isFocus Nothing = Bool -> X Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    False
    isFocus (Just w :: a
    w) = do Maybe (Stack Window)
    ms <- (Workspace String (Layout Window) Window -> Maybe (Stack Window)
    forall i l a. Workspace i l a -> Maybe (Stack a)
    W.stack (Workspace String (Layout Window) Window -> Maybe (Stack Window))
    -> (StackSet String (Layout Window) Window ScreenId ScreenDetail
        -> Workspace String (Layout Window) Window)
    -> StackSet String (Layout Window) Window ScreenId ScreenDetail
    -> Maybe (Stack Window)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Screen String (Layout Window) Window ScreenId ScreenDetail
    -> Workspace String (Layout Window) Window
    forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
    W.workspace (Screen String (Layout Window) Window ScreenId ScreenDetail
     -> Workspace String (Layout Window) Window)
    -> (StackSet String (Layout Window) Window ScreenId ScreenDetail
        -> Screen String (Layout Window) Window ScreenId ScreenDetail)
    -> StackSet String (Layout Window) Window ScreenId ScreenDetail
    -> Workspace String (Layout Window) Window
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . StackSet String (Layout Window) Window ScreenId ScreenDetail
    -> Screen String (Layout Window) Window ScreenId ScreenDetail
    forall i l a sid sd. StackSet i l a sid sd -> Screen i l a sid sd
    W.current) (StackSet String (Layout Window) Window ScreenId ScreenDetail
     -> Maybe (Stack Window))
    -> X (StackSet String (Layout Window) Window ScreenId ScreenDetail)
    -> X (Maybe (Stack Window))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` (XState
     -> StackSet String (Layout Window) Window ScreenId ScreenDetail)
    -> X (StackSet String (Layout Window) Window ScreenId ScreenDetail)
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets XState
    -> StackSet String (Layout Window) Window ScreenId ScreenDetail
    windowset
                          Bool -> X Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Bool -> X Bool) -> Bool -> X Bool
    forall a b. (a -> b) -> a -> b
    $ Bool -> (Stack Window -> Bool) -> Maybe (Stack Window) -> Bool
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Bool
    False (\s :: Stack Window
    s -> a -> String
    forall a. Show a => a -> String
    show a
    w String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    == Window -> String
    forall a. Show a => a -> String
    show (Stack Window -> Window
    forall a. Stack a -> a
    W.focus Stack Window
    s)) Maybe (Stack Window)
    ms

    --------------------------------------------------------------------------------
    calcNum :: Int -> Limit p -> Int
    calcNum :: Int -> Limit p -> Int
    calcNum tot :: Int
    tot num :: Limit p
    num = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max 1 (Int -> Int) -> Int -> Int
    forall a b. (a -> b) -> a -> b
    $ case Limit p
    num of LimitN i :: Int
    i     -> Int
    i
                                          LimitR (_,r :: Rational
    r) -> Rational -> Int
    forall a b. (RealFrac a, Integral b) => a -> b
    ceiling (Rational -> Int) -> Rational -> Int
    forall a b. (a -> b) -> a -> b
    $ Rational
    r Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Int -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    tot
                                          LimitP _     -> 1

    --------------------------------------------------------------------------------
    -- | Split given list of objects (i.e. windows) using predicate.
    splitBy :: (Predicate p a) => p -> [a] -> X ([a], [a])
    splitBy :: p -> [a] -> X ([a], [a])
    splitBy prop :: p
    prop = (([a], [a]) -> a -> X ([a], [a]))
    -> ([a], [a]) -> [a] -> X ([a], [a])
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM ([a], [a]) -> a -> X ([a], [a])
    forall a. Predicate p a => ([a], [a]) -> a -> X ([a], [a])
    step ([], [])
      where
        step :: ([a], [a]) -> a -> X ([a], [a])
    step (good :: [a]
    good, bad :: [a]
    bad) w :: a
    w = do
          Bool
    ok <- p -> a -> X Bool
    forall p w. Predicate p w => p -> w -> X Bool
    checkPredicate p
    prop a
    w
          ([a], [a]) -> X ([a], [a])
    forall (m :: * -> *) a. Monad m => a -> m a
    return (([a], [a]) -> X ([a], [a])) -> ([a], [a]) -> X ([a], [a])
    forall a b. (a -> b) -> a -> b
    $ if Bool
    ok
                    then (a
    wa -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :[a]
    good, [a]
    bad)
                    else ([a]
    good,   a
    wa -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :[a]
    bad)

    --------------------------------------------------------------------------------
    splitStack :: forall a p. (Eq a, Predicate p a)
               => Maybe (W.Stack a) -- ^ Window set.
               -> Limit p           -- ^ How to split the stack.
               -> Maybe a           -- ^ The window that was focused in this layout.
               -> Maybe a           -- ^ The window that was focused in the next layout.
               -> X (Maybe (W.Stack a), Maybe (W.Stack a), Maybe a, Maybe a)
    splitStack :: Maybe (Stack a)
    -> Limit p
    -> Maybe a
    -> Maybe a
    -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    splitStack Nothing _ _ _ = (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (Stack a)
    forall a. Maybe a
    Nothing, Maybe (Stack a)
    forall a. Maybe a
    Nothing, Maybe a
    forall a. Maybe a
    Nothing, Maybe a
    forall a. Maybe a
    Nothing)
    splitStack (Just s :: Stack a
    s) limit :: Limit p
    limit subFocus :: Maybe a
    subFocus nextFocus :: Maybe a
    nextFocus =
      case Limit p
    limit of
        LimitN _    -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    splitN
        LimitR _    -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    splitN
        LimitP prop :: p
    prop -> p -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    forall p.
    Predicate p a =>
    p -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    splitP p
    prop

      where
        ws :: [a]
    ws        = Stack a -> [a]
    forall a. Stack a -> [a]
    W.integrate Stack a
    s
        n :: Int
    n         = Int -> Limit p -> Int
    forall p. Int -> Limit p -> Int
    calcNum ([a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    ws) Limit p
    limit
        subl :: [a]
    subl      = Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    n [a]
    ws
        nextl :: [a]
    nextl     = Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    drop Int
    n [a]
    ws
        subFocus' :: [a] -> Maybe a
    subFocus' xs :: [a]
    xs  = [a] -> Maybe a -> Maybe a
    foc [a]
    xs Maybe a
    subFocus
        nextFocus' :: [a] -> Maybe a
    nextFocus' xs :: [a]
    xs = [a] -> Maybe a -> Maybe a
    foc [a]
    xs Maybe a
    nextFocus

        -- Pick a new focused window if necessary.
        foc :: [a] -> Maybe a -> Maybe a
        foc :: [a] -> Maybe a -> Maybe a
    foc [] _                           = Maybe a
    forall a. Maybe a
    Nothing
        foc l :: [a]
    l f :: Maybe a
    f | Stack a -> a
    forall a. Stack a -> a
    W.focus Stack a
    s a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [a]
    l       = a -> Maybe a
    forall a. a -> Maybe a
    Just (Stack a -> a
    forall a. Stack a -> a
    W.focus Stack a
    s)
                | Bool -> (a -> Bool) -> Maybe a -> Bool
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Bool
    False (a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [a]
    l) Maybe a
    f = Maybe a
    f
                | Bool
    otherwise                = [a] -> Maybe a
    forall a. [a] -> Maybe a
    listToMaybe [a]
    l

        -- Split based on max number of windows.
        splitN :: X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    splitN = (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ( Maybe a -> [a] -> Maybe (Stack a)
    forall q. Eq q => Maybe q -> [q] -> Maybe (Stack q)
    differentiate' ([a] -> Maybe a
    subFocus' [a]
    subl)   [a]
    subl
                        , Maybe a -> [a] -> Maybe (Stack a)
    forall q. Eq q => Maybe q -> [q] -> Maybe (Stack q)
    differentiate' ([a] -> Maybe a
    nextFocus' [a]
    nextl) [a]
    nextl
                        , [a] -> Maybe a
    subFocus'  [a]
    subl
                        , [a] -> Maybe a
    nextFocus' [a]
    nextl
                        )

        -- Split based on a predicate.
        splitP :: p -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    splitP prop :: p
    prop = do
          (this :: [a]
    this, other :: [a]
    other) <- p -> [a] -> X ([a], [a])
    forall p a. Predicate p a => p -> [a] -> X ([a], [a])
    splitBy p
    prop [a]
    ws
          (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    -> X (Maybe (Stack a), Maybe (Stack a), Maybe a, Maybe a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ( Maybe a -> [a] -> Maybe (Stack a)
    forall q. Eq q => Maybe q -> [q] -> Maybe (Stack q)
    differentiate' ([a] -> Maybe a
    subFocus' [a]
    this)   [a]
    this
                 , Maybe a -> [a] -> Maybe (Stack a)
    forall q. Eq q => Maybe q -> [q] -> Maybe (Stack q)
    differentiate' ([a] -> Maybe a
    nextFocus' [a]
    other) [a]
    other
                 , [a] -> Maybe a
    subFocus' [a]
    this
                 , [a] -> Maybe a
    nextFocus' [a]
    other
                 )

    --------------------------------------------------------------------------------
    calcArea :: SubBox -> Rectangle -> Rectangle
    calcArea :: SubBox -> Rectangle -> Rectangle
    calcArea (SubBox xpos :: SubMeasure
    xpos ypos :: SubMeasure
    ypos width :: SubMeasure
    width height :: SubMeasure
    height) rect :: Rectangle
    rect =
        Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle (Rectangle -> Position
    rect_x Rectangle
    rect Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Dimension -> Position
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    xpos')
                  (Rectangle -> Position
    rect_y Rectangle
    rect Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Dimension -> Position
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    ypos')
                  Dimension
    width' Dimension
    height'
      where
        xpos' :: Dimension
    xpos' = Bool -> SubMeasure -> Dimension -> Dimension
    forall a b. (Integral a, Num b) => Bool -> SubMeasure -> a -> b
    calc Bool
    False SubMeasure
    xpos (Dimension -> Dimension) -> Dimension -> Dimension
    forall a b. (a -> b) -> a -> b
    $ Rectangle -> Dimension
    rect_width Rectangle
    rect
        ypos' :: Dimension
    ypos' = Bool -> SubMeasure -> Dimension -> Dimension
    forall a b. (Integral a, Num b) => Bool -> SubMeasure -> a -> b
    calc Bool
    False SubMeasure
    ypos (Dimension -> Dimension) -> Dimension -> Dimension
    forall a b. (a -> b) -> a -> b
    $ Rectangle -> Dimension
    rect_height Rectangle
    rect
        width' :: Dimension
    width' = Bool -> SubMeasure -> Dimension -> Dimension
    forall a b. (Integral a, Num b) => Bool -> SubMeasure -> a -> b
    calc Bool
    True SubMeasure
    width (Dimension -> Dimension) -> Dimension -> Dimension
    forall a b. (a -> b) -> a -> b
    $ Rectangle -> Dimension
    rect_width Rectangle
    rect Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Dimension
    xpos'
        height' :: Dimension
    height' = Bool -> SubMeasure -> Dimension -> Dimension
    forall a b. (Integral a, Num b) => Bool -> SubMeasure -> a -> b
    calc Bool
    True SubMeasure
    height (Dimension -> Dimension) -> Dimension -> Dimension
    forall a b. (a -> b) -> a -> b
    $ Rectangle -> Dimension
    rect_height Rectangle
    rect Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Dimension
    ypos'

        calc :: Bool -> SubMeasure -> a -> b
    calc zneg :: Bool
    zneg val :: SubMeasure
    val tot :: a
    tot = Int -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> b) -> Int -> b
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    min (a -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    tot) (Int -> Int) -> Int -> Int
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max 0 (Int -> Int) -> Int -> Int
    forall a b. (a -> b) -> a -> b
    $
            case SubMeasure
    val of Rel v :: Rational
    v -> Rational -> Int
    forall a b. (RealFrac a, Integral b) => a -> b
    floor (Rational -> Int) -> Rational -> Int
    forall a b. (a -> b) -> a -> b
    $ Rational
    v Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * a -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    tot
                        Abs v :: Int
    v -> if Int
    vInt -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <0 Bool -> Bool -> Bool
    || (Bool
    zneg Bool -> Bool -> Bool
    && Int
    vInt -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    ==0)
                                   then a -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    tot Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    v
                                   else Int
    v

    --------------------------------------------------------------------------------
    differentiate' :: Eq q => Maybe q -> [q] -> Maybe (W.Stack q)
    differentiate' :: Maybe q -> [q] -> Maybe (Stack q)
    differentiate' _ [] = Maybe (Stack q)
    forall a. Maybe a
    Nothing
    differentiate' Nothing w :: [q]
    w = [q] -> Maybe (Stack q)
    forall a. [a] -> Maybe (Stack a)
    W.differentiate [q]
    w
    differentiate' (Just f :: q
    f) w :: [q]
    w
        | q
    f q -> [q] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [q]
    w = Stack q -> Maybe (Stack q)
    forall a. a -> Maybe a
    Just $WStack :: forall a. a -> [a] -> [a] -> Stack a
    W.Stack { focus :: q
    W.focus = q
    f
                                    , up :: [q]
    W.up    = [q] -> [q]
    forall a. [a] -> [a]
    reverse ([q] -> [q]) -> [q] -> [q]
    forall a b. (a -> b) -> a -> b
    $ (q -> Bool) -> [q] -> [q]
    forall a. (a -> Bool) -> [a] -> [a]
    takeWhile (q -> q -> Bool
    forall a. Eq a => a -> a -> Bool
    /=q
    f) [q]
    w
                                    , down :: [q]
    W.down  = [q] -> [q]
    forall a. [a] -> [a]
    tail ([q] -> [q]) -> [q] -> [q]
    forall a b. (a -> b) -> a -> b
    $ (q -> Bool) -> [q] -> [q]
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhile (q -> q -> Bool
    forall a. Eq a => a -> a -> Bool
    /=q
    f) [q]
    w
                                    }
        | Bool
    otherwise = [q] -> Maybe (Stack q)
    forall a. [a] -> Maybe (Stack a)
    W.differentiate [q]
    w