{-# 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