    {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, PatternGuards #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Layout.ResizeScreen
    -- Description :  A layout transformer to have a layout respect a given screen geometry.
    -- Copyright   :  (c) 2007 Andrea Rossato
    -- License     :  BSD-style (see xmonad/LICENSE)
    --
    -- Maintainer  :  andrea.rossato@unibz.it
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- A layout transformer to have a layout respect a given screen
    -- geometry. Mostly used with "XMonad.Layout.Decoration" (the
    -- Horizontal and the Vertical version will react to SetTheme and
    -- change their dimension accordingly.
    -----------------------------------------------------------------------------

    module XMonad.Layout.ResizeScreen
        ( -- * Usage:
          -- $usage
          resizeHorizontal, resizeVertical
        , resizeHorizontalRight, resizeVerticalBottom
        , withNewRectangle
        , ResizeScreen (..)
        , ResizeMode
        ) where

    import XMonad
    import XMonad.Layout.Decoration

    -- $usage
    -- You can use this module by importing it into your
    -- @xmonad.hs@ file:
    --
    -- > import XMonad.Layout.ResizeScreen
    --
    -- and modifying your layoutHook as follows (for example):
    --
    -- > layoutHook = resizeHorizontal 40 Full
    --
    -- For more detailed instructions on editing the layoutHook see
    -- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial> and
    -- "XMonad.Doc.Extending#Editing_the_layout_hook".

    resizeHorizontal :: Int -> l a -> ModifiedLayout ResizeScreen l a
    resizeHorizontal :: forall (l :: * -> *) a.
    Int -> l a -> ModifiedLayout ResizeScreen l a
    resizeHorizontal Int
    i = ResizeScreen a -> l a -> ModifiedLayout ResizeScreen l a
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout (ResizeMode -> Int -> ResizeScreen a
    forall a. ResizeMode -> Int -> ResizeScreen a
    ResizeScreen ResizeMode
    L Int
    i)

    resizeVertical :: Int -> l a -> ModifiedLayout ResizeScreen l a
    resizeVertical :: forall (l :: * -> *) a.
    Int -> l a -> ModifiedLayout ResizeScreen l a
    resizeVertical Int
    i = ResizeScreen a -> l a -> ModifiedLayout ResizeScreen l a
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout (ResizeMode -> Int -> ResizeScreen a
    forall a. ResizeMode -> Int -> ResizeScreen a
    ResizeScreen ResizeMode
    T Int
    i)

    resizeHorizontalRight :: Int -> l a -> ModifiedLayout ResizeScreen l a
    resizeHorizontalRight :: forall (l :: * -> *) a.
    Int -> l a -> ModifiedLayout ResizeScreen l a
    resizeHorizontalRight Int
    i = ResizeScreen a -> l a -> ModifiedLayout ResizeScreen l a
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout (ResizeMode -> Int -> ResizeScreen a
    forall a. ResizeMode -> Int -> ResizeScreen a
    ResizeScreen ResizeMode
    R Int
    i)

    resizeVerticalBottom :: Int -> l a -> ModifiedLayout ResizeScreen l a
    resizeVerticalBottom :: forall (l :: * -> *) a.
    Int -> l a -> ModifiedLayout ResizeScreen l a
    resizeVerticalBottom Int
    i = ResizeScreen a -> l a -> ModifiedLayout ResizeScreen l a
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout (ResizeMode -> Int -> ResizeScreen a
    forall a. ResizeMode -> Int -> ResizeScreen a
    ResizeScreen ResizeMode
    B Int
    i)

    withNewRectangle  :: Rectangle -> l a -> ModifiedLayout ResizeScreen l a
    withNewRectangle :: forall (l :: * -> *) a.
    Rectangle -> l a -> ModifiedLayout ResizeScreen l a
    withNewRectangle Rectangle
    r = ResizeScreen a -> l a -> ModifiedLayout ResizeScreen l a
    forall (m :: * -> *) (l :: * -> *) a.
    m a -> l a -> ModifiedLayout m l a
    ModifiedLayout (Rectangle -> ResizeScreen a
    forall a. Rectangle -> ResizeScreen a
    WithNewScreen Rectangle
    r)

    data ResizeScreen a = ResizeScreen ResizeMode Int
                        | WithNewScreen Rectangle
                          deriving (ReadPrec [ResizeScreen a]
    ReadPrec (ResizeScreen a)
    Int -> ReadS (ResizeScreen a)
    ReadS [ResizeScreen a]
    (Int -> ReadS (ResizeScreen a))
    -> ReadS [ResizeScreen a]
    -> ReadPrec (ResizeScreen a)
    -> ReadPrec [ResizeScreen a]
    -> Read (ResizeScreen a)
    forall a. ReadPrec [ResizeScreen a]
    forall a. ReadPrec (ResizeScreen a)
    forall a. Int -> ReadS (ResizeScreen a)
    forall a. ReadS [ResizeScreen a]
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: forall a. Int -> ReadS (ResizeScreen a)
    readsPrec :: Int -> ReadS (ResizeScreen a)
    $creadList :: forall a. ReadS [ResizeScreen a]
    readList :: ReadS [ResizeScreen a]
    $creadPrec :: forall a. ReadPrec (ResizeScreen a)
    readPrec :: ReadPrec (ResizeScreen a)
    $creadListPrec :: forall a. ReadPrec [ResizeScreen a]
    readListPrec :: ReadPrec [ResizeScreen a]
    Read, Int -> ResizeScreen a -> ShowS
    [ResizeScreen a] -> ShowS
    ResizeScreen a -> String
    (Int -> ResizeScreen a -> ShowS)
    -> (ResizeScreen a -> String)
    -> ([ResizeScreen a] -> ShowS)
    -> Show (ResizeScreen a)
    forall a. Int -> ResizeScreen a -> ShowS
    forall a. [ResizeScreen a] -> ShowS
    forall a. ResizeScreen a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Int -> ResizeScreen a -> ShowS
    showsPrec :: Int -> ResizeScreen a -> ShowS
    $cshow :: forall a. ResizeScreen a -> String
    show :: ResizeScreen a -> String
    $cshowList :: forall a. [ResizeScreen a] -> ShowS
    showList :: [ResizeScreen a] -> ShowS
    Show)

    data ResizeMode = T | B | L | R deriving (ReadPrec [ResizeMode]
    ReadPrec ResizeMode
    Int -> ReadS ResizeMode
    ReadS [ResizeMode]
    (Int -> ReadS ResizeMode)
    -> ReadS [ResizeMode]
    -> ReadPrec ResizeMode
    -> ReadPrec [ResizeMode]
    -> Read ResizeMode
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS ResizeMode
    readsPrec :: Int -> ReadS ResizeMode
    $creadList :: ReadS [ResizeMode]
    readList :: ReadS [ResizeMode]
    $creadPrec :: ReadPrec ResizeMode
    readPrec :: ReadPrec ResizeMode
    $creadListPrec :: ReadPrec [ResizeMode]
    readListPrec :: ReadPrec [ResizeMode]
    Read, Int -> ResizeMode -> ShowS
    [ResizeMode] -> ShowS
    ResizeMode -> String
    (Int -> ResizeMode -> ShowS)
    -> (ResizeMode -> String)
    -> ([ResizeMode] -> ShowS)
    -> Show ResizeMode
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ResizeMode -> ShowS
    showsPrec :: Int -> ResizeMode -> ShowS
    $cshow :: ResizeMode -> String
    show :: ResizeMode -> String
    $cshowList :: [ResizeMode] -> ShowS
    showList :: [ResizeMode] -> ShowS
    Show)

    instance LayoutModifier ResizeScreen a where
        modifyLayout :: forall (l :: * -> *).
    LayoutClass l a =>
    ResizeScreen a
    -> Workspace String (l a) a
    -> Rectangle
    -> X ([(a, Rectangle)], Maybe (l a))
    modifyLayout ResizeScreen a
    m Workspace String (l a) a
    ws (Rectangle Position
    x Position
    y Dimension
    w Dimension
    h)
            | ResizeScreen ResizeMode
    L Int
    i <- ResizeScreen a
    m = Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    resize (Rectangle -> X ([(a, Rectangle)], Maybe (l a)))
    -> Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    forall a b. (a -> b) -> a -> b
    $ Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle (Position
    x Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Int -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    i) Position
    y (Dimension
    w Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Int -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    i) Dimension
    h
            | ResizeScreen ResizeMode
    R Int
    i <- ResizeScreen a
    m = Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    resize (Rectangle -> X ([(a, Rectangle)], Maybe (l a)))
    -> Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    forall a b. (a -> b) -> a -> b
    $ Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x          Position
    y (Dimension
    w Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Int -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    i) Dimension
    h
            | ResizeScreen ResizeMode
    T Int
    i <- ResizeScreen a
    m = Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    resize (Rectangle -> X ([(a, Rectangle)], Maybe (l a)))
    -> Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    forall a b. (a -> b) -> a -> b
    $ Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x (Position
    y Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Int -> Position
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    i) Dimension
    w (Dimension
    h Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Int -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    i)
            | ResizeScreen ResizeMode
    B Int
    i <- ResizeScreen a
    m = Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    resize (Rectangle -> X ([(a, Rectangle)], Maybe (l a)))
    -> Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    forall a b. (a -> b) -> a -> b
    $ Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x  Position
    y         Dimension
    w (Dimension
    h Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Int -> Dimension
    forall a b. (Integral a, Num b) => a -> b
    fi Int
    i)
            | WithNewScreen  Rectangle
    r <- ResizeScreen a
    m = Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    resize Rectangle
    r
           where resize :: Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    resize = Workspace String (l a) a
    -> Rectangle -> X ([(a, Rectangle)], Maybe (l a))
    forall (layout :: * -> *) a.
    LayoutClass layout a =>
    Workspace String (layout a) a
    -> Rectangle -> X ([(a, Rectangle)], Maybe (layout a))
    runLayout Workspace String (l a) a
    ws

        pureMess :: ResizeScreen a -> SomeMessage -> Maybe (ResizeScreen a)
    pureMess (ResizeScreen ResizeMode
    d Int
    _) SomeMessage
    m
            | Just (SetTheme Theme
    t) <- SomeMessage -> Maybe DecorationMsg
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    m = ResizeScreen a -> Maybe (ResizeScreen a)
    forall a. a -> Maybe a
    Just (ResizeScreen a -> Maybe (ResizeScreen a))
    -> ResizeScreen a -> Maybe (ResizeScreen a)
    forall a b. (a -> b) -> a -> b
    $ ResizeMode -> Int -> ResizeScreen a
    forall a. ResizeMode -> Int -> ResizeScreen a
    ResizeScreen ResizeMode
    d (Dimension -> Int
    forall a b. (Integral a, Num b) => a -> b
    fi (Dimension -> Int) -> Dimension -> Int
    forall a b. (a -> b) -> a -> b
    $ Theme -> Dimension
    decoHeight Theme
    t)
        pureMess ResizeScreen a
    _ SomeMessage
    _ = Maybe (ResizeScreen a)
    forall a. Maybe a
    Nothing