{-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses, TupleSections #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Layout.HintedGrid
-- Description :  A layout that puts all windows in a square grid while obeying their size hints.
-- Copyright   :  (c) Lukas Mai
-- License     :  BSD-style (see LICENSE)
--
-- Maintainer  :  <l.mai@web.de>
-- Stability   :  unstable
-- Portability :  unportable
--
-- A not so simple layout that attempts to put all windows in a square grid
-- while obeying their size hints.
--
-----------------------------------------------------------------------------

module XMonad.Layout.HintedGrid (
    -- * Usage
    -- $usage
    Grid(..), arrange, defaultRatio
) where

import Prelude hiding ((.))

import XMonad
import XMonad.Prelude (replicateM, sortBy, sortOn)
import XMonad.StackSet

import Control.Monad.State (runState)
import Data.Ord

infixr 9 .
(.) :: (Functor f) => (a -> b) -> f a -> f b
. :: forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
(.) = (a -> b) -> f a -> f b
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap

-- $usage
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Layout.HintedGrid
--
-- Then edit your @layoutHook@ by adding the 'Grid' layout:
--
-- > myLayout = Grid False ||| Full ||| etc..
-- > main = xmonad def { layoutHook = myLayout }
--
-- You can also specify an aspect ratio for Grid to strive for with the
-- GridRatio constructor:
--
-- > myLayout = GridRatio (4/3) False ||| etc.
--
-- 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".

-- | Automatic mirroring of hinted layouts doesn't work very well, so this
-- 'Grid' comes with built-in mirroring. @Grid False@ is the normal layout,
-- @Grid True@ is the mirrored variant (rotated by 90 degrees).
data Grid a = Grid Bool | GridRatio Double Bool deriving (ReadPrec [Grid a]
ReadPrec (Grid a)
Int -> ReadS (Grid a)
ReadS [Grid a]
(Int -> ReadS (Grid a))
-> ReadS [Grid a]
-> ReadPrec (Grid a)
-> ReadPrec [Grid a]
-> Read (Grid a)
forall a. ReadPrec [Grid a]
forall a. ReadPrec (Grid a)
forall a. Int -> ReadS (Grid a)
forall a. ReadS [Grid a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: forall a. Int -> ReadS (Grid a)
readsPrec :: Int -> ReadS (Grid a)
$creadList :: forall a. ReadS [Grid a]
readList :: ReadS [Grid a]
$creadPrec :: forall a. ReadPrec (Grid a)
readPrec :: ReadPrec (Grid a)
$creadListPrec :: forall a. ReadPrec [Grid a]
readListPrec :: ReadPrec [Grid a]
Read, Int -> Grid a -> ShowS
[Grid a] -> ShowS
Grid a -> String
(Int -> Grid a -> ShowS)
-> (Grid a -> String) -> ([Grid a] -> ShowS) -> Show (Grid a)
forall a. Int -> Grid a -> ShowS
forall a. [Grid a] -> ShowS
forall a. Grid a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Int -> Grid a -> ShowS
showsPrec :: Int -> Grid a -> ShowS
$cshow :: forall a. Grid a -> String
show :: Grid a -> String
$cshowList :: forall a. [Grid a] -> ShowS
showList :: [Grid a] -> ShowS
Show)

defaultRatio :: Double
defaultRatio :: Double
defaultRatio = Double
16Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
9

instance LayoutClass Grid Window where
    doLayout :: Grid Window
-> Rectangle
-> Stack Window
-> X ([(Window, Rectangle)], Maybe (Grid Window))
doLayout (Grid Bool
m)        Rectangle
r Stack Window
w = Grid Window
-> Rectangle
-> Stack Window
-> X ([(Window, Rectangle)], Maybe (Grid Window))
forall (layout :: * -> *) a.
LayoutClass layout a =>
layout a
-> Rectangle -> Stack a -> X ([(a, Rectangle)], Maybe (layout a))
doLayout (Double -> Bool -> Grid Window
forall a. Double -> Bool -> Grid a
GridRatio Double
defaultRatio Bool
m) Rectangle
r Stack Window
w
    doLayout (GridRatio Double
d Bool
m) Rectangle
r Stack Window
w = (, Maybe (Grid Window)
forall a. Maybe a
Nothing) ([(Window, Rectangle)]
 -> ([(Window, Rectangle)], Maybe (Grid Window)))
-> X [(Window, Rectangle)]
-> X ([(Window, Rectangle)], Maybe (Grid Window))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. Double -> Bool -> Rectangle -> [Window] -> X [(Window, Rectangle)]
arrange Double
d Bool
m Rectangle
r (Stack Window -> [Window]
forall a. Stack a -> [a]
integrate Stack Window
w)

replicateS :: Int -> (a -> (b, a)) -> a -> ([b], a)
replicateS :: forall a b. Int -> (a -> (b, a)) -> a -> ([b], a)
replicateS Int
n a -> (b, a)
f = State a [b] -> a -> ([b], a)
forall s a. State s a -> s -> (a, s)
runState (State a [b] -> a -> ([b], a))
-> (StateT a Identity b -> State a [b])
-> StateT a Identity b
-> a
-> ([b], a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. Int -> StateT a Identity b -> State a [b]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
n (StateT a Identity b -> a -> ([b], a))
-> StateT a Identity b -> a -> ([b], a)
forall a b. (a -> b) -> a -> b
$ do (b
a,a
s) <- (a -> (b, a)) -> StateT a Identity (b, a)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets a -> (b, a)
f; a -> StateT a Identity ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put a
s; b -> StateT a Identity b
forall a. a -> StateT a Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return b
a

doColumn :: Dimension -> Dimension -> Dimension -> [D -> D] -> [D]
doColumn :: Dimension
-> Dimension
-> Dimension
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> [(Dimension, Dimension)]
doColumn Dimension
width Dimension
height Dimension
k [(Dimension, Dimension) -> (Dimension, Dimension)]
adjs =
    let
        ([Int]
ind, [(Dimension, Dimension) -> (Dimension, Dimension)]
fs) = [(Int, (Dimension, Dimension) -> (Dimension, Dimension))]
-> ([Int], [(Dimension, Dimension) -> (Dimension, Dimension)])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(Int, (Dimension, Dimension) -> (Dimension, Dimension))]
 -> ([Int], [(Dimension, Dimension) -> (Dimension, Dimension)]))
-> ([(Dimension, Dimension) -> (Dimension, Dimension)]
    -> [(Int, (Dimension, Dimension) -> (Dimension, Dimension))])
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> ([Int], [(Dimension, Dimension) -> (Dimension, Dimension)])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. ((Int, (Dimension, Dimension) -> (Dimension, Dimension))
 -> Dimension)
-> [(Int, (Dimension, Dimension) -> (Dimension, Dimension))]
-> [(Int, (Dimension, Dimension) -> (Dimension, Dimension))]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn ((Dimension, Dimension) -> Dimension
forall a b. (a, b) -> b
snd ((Dimension, Dimension) -> Dimension)
-> ((Int, (Dimension, Dimension) -> (Dimension, Dimension))
    -> (Dimension, Dimension))
-> (Int, (Dimension, Dimension) -> (Dimension, Dimension))
-> Dimension
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. (((Dimension, Dimension) -> (Dimension, Dimension))
-> (Dimension, Dimension) -> (Dimension, Dimension)
forall a b. (a -> b) -> a -> b
$ (Dimension
width, Dimension
height)) (((Dimension, Dimension) -> (Dimension, Dimension))
 -> (Dimension, Dimension))
-> ((Int, (Dimension, Dimension) -> (Dimension, Dimension))
    -> (Dimension, Dimension) -> (Dimension, Dimension))
-> (Int, (Dimension, Dimension) -> (Dimension, Dimension))
-> (Dimension, Dimension)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. (Int, (Dimension, Dimension) -> (Dimension, Dimension))
-> (Dimension, Dimension) -> (Dimension, Dimension)
forall a b. (a, b) -> b
snd) ([(Int, (Dimension, Dimension) -> (Dimension, Dimension))]
 -> [(Int, (Dimension, Dimension) -> (Dimension, Dimension))])
-> ([(Dimension, Dimension) -> (Dimension, Dimension)]
    -> [(Int, (Dimension, Dimension) -> (Dimension, Dimension))])
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> [(Int, (Dimension, Dimension) -> (Dimension, Dimension))]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. [Int]
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> [(Int, (Dimension, Dimension) -> (Dimension, Dimension))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0 :: Int ..] ([(Dimension, Dimension) -> (Dimension, Dimension)]
 -> ([Int], [(Dimension, Dimension) -> (Dimension, Dimension)]))
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> ([Int], [(Dimension, Dimension) -> (Dimension, Dimension)])
forall a b. (a -> b) -> a -> b
$ [(Dimension, Dimension) -> (Dimension, Dimension)]
adjs
        (Dimension
_, [(Dimension, Dimension)]
ds) = Dimension
-> Dimension
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> (Dimension, [(Dimension, Dimension)])
forall {t} {a}.
Integral t =>
t -> t -> [(Dimension, t) -> (a, t)] -> (t, [(a, t)])
doC Dimension
height Dimension
k [(Dimension, Dimension) -> (Dimension, Dimension)]
fs
    in
    ((Int, (Dimension, Dimension)) -> (Dimension, Dimension))
-> [(Int, (Dimension, Dimension))] -> [(Dimension, Dimension)]
forall a b. (a -> b) -> [a] -> [b]
map (Int, (Dimension, Dimension)) -> (Dimension, Dimension)
forall a b. (a, b) -> b
snd ([(Int, (Dimension, Dimension))] -> [(Dimension, Dimension)])
-> ([(Dimension, Dimension)] -> [(Int, (Dimension, Dimension))])
-> [(Dimension, Dimension)]
-> [(Dimension, Dimension)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. ((Int, (Dimension, Dimension))
 -> (Int, (Dimension, Dimension)) -> Ordering)
-> [(Int, (Dimension, Dimension))]
-> [(Int, (Dimension, Dimension))]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (((Int, (Dimension, Dimension)) -> Int)
-> (Int, (Dimension, Dimension))
-> (Int, (Dimension, Dimension))
-> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (Int, (Dimension, Dimension)) -> Int
forall a b. (a, b) -> a
fst) ([(Int, (Dimension, Dimension))]
 -> [(Int, (Dimension, Dimension))])
-> ([(Dimension, Dimension)] -> [(Int, (Dimension, Dimension))])
-> [(Dimension, Dimension)]
-> [(Int, (Dimension, Dimension))]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. [Int]
-> [(Dimension, Dimension)] -> [(Int, (Dimension, Dimension))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
ind ([(Dimension, Dimension)] -> [(Dimension, Dimension)])
-> [(Dimension, Dimension)] -> [(Dimension, Dimension)]
forall a b. (a -> b) -> a -> b
$ [(Dimension, Dimension)]
ds
    where
    doC :: t -> t -> [(Dimension, t) -> (a, t)] -> (t, [(a, t)])
doC t
h t
_ [] = (t
h, [])
    doC t
h t
n ((Dimension, t) -> (a, t)
f : [(Dimension, t) -> (a, t)]
fs) = ((a, t)
adj (a, t) -> [(a, t)] -> [(a, t)]
forall a. a -> [a] -> [a]
:) ([(a, t)] -> [(a, t)]) -> (t, [(a, t)]) -> (t, [(a, t)])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. t -> t -> [(Dimension, t) -> (a, t)] -> (t, [(a, t)])
doC (t
h t -> t -> t
forall a. Num a => a -> a -> a
- t
h') (t
n t -> t -> t
forall a. Num a => a -> a -> a
- t
1) [(Dimension, t) -> (a, t)]
fs
        where
        adj :: (a, t)
adj@(a
_, t
h') = (Dimension, t) -> (a, t)
f (Dimension
width, t
h t -> t -> t
forall a. Integral a => a -> a -> a
`div` t
n)

doRect :: Dimension -> Dimension -> Dimension -> [[D -> D]] -> [Rectangle]
doRect :: Dimension
-> Dimension
-> Dimension
-> [[(Dimension, Dimension) -> (Dimension, Dimension)]]
-> [Rectangle]
doRect Dimension
height = Dimension
-> Dimension
-> [[(Dimension, Dimension) -> (Dimension, Dimension)]]
-> [Rectangle]
doR
    where
    doR :: Dimension
-> Dimension
-> [[(Dimension, Dimension) -> (Dimension, Dimension)]]
-> [Rectangle]
doR Dimension
_ Dimension
_ [] = []
    doR Dimension
width Dimension
n ([(Dimension, Dimension) -> (Dimension, Dimension)]
c : [[(Dimension, Dimension) -> (Dimension, Dimension)]]
cs) =
        let
            v :: Dimension
v = Int -> Dimension
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Dimension) -> Int -> Dimension
forall a b. (a -> b) -> a -> b
$ [(Dimension, Dimension) -> (Dimension, Dimension)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Dimension, Dimension) -> (Dimension, Dimension)]
c
            c' :: [(Dimension, Dimension)]
c' = Dimension
-> Dimension
-> Dimension
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> [(Dimension, Dimension)]
doColumn (Dimension
width Dimension -> Dimension -> Dimension
forall a. Integral a => a -> a -> a
`div` Dimension
n) Dimension
height Dimension
v [(Dimension, Dimension) -> (Dimension, Dimension)]
c
            ([Dimension]
ws, [Dimension]
hs) = [(Dimension, Dimension)] -> ([Dimension], [Dimension])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Dimension, Dimension)]
c'
            maxw :: Dimension
maxw = [Dimension] -> Dimension
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Dimension]
ws
            height' :: Dimension
height' = [Dimension] -> Dimension
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Dimension]
hs
            hbonus :: Dimension
hbonus = Dimension
height Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
height'
            hsingle :: Dimension
hsingle = Dimension
hbonus Dimension -> Dimension -> Dimension
forall a. Integral a => a -> a -> a
`div` Dimension
v
            hoffset :: Dimension
hoffset = Dimension
hsingle Dimension -> Dimension -> Dimension
forall a. Integral a => a -> a -> a
`div` Dimension
2
            width' :: Dimension
width' = Dimension
width Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
maxw
            ys :: [Dimension]
ys = (Dimension -> Dimension) -> [Dimension] -> [Dimension]
forall a b. (a -> b) -> [a] -> [b]
map ((Dimension
height Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
-) (Dimension -> Dimension)
-> (Dimension -> Dimension) -> Dimension -> Dimension
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
subtract Dimension
hoffset) ([Dimension] -> [Dimension])
-> ([Dimension] -> [Dimension]) -> [Dimension] -> [Dimension]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. (Dimension -> Dimension -> Dimension) -> [Dimension] -> [Dimension]
forall a. (a -> a -> a) -> [a] -> [a]
scanl1 Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
(+) ([Dimension] -> [Dimension])
-> ([Dimension] -> [Dimension]) -> [Dimension] -> [Dimension]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. (Dimension -> Dimension) -> [Dimension] -> [Dimension]
forall a b. (a -> b) -> [a] -> [b]
map (Dimension
hsingle Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
+) ([Dimension] -> [Dimension]) -> [Dimension] -> [Dimension]
forall a b. (a -> b) -> a -> b
$ [Dimension]
hs
            xs :: [Dimension]
xs = (Dimension -> Dimension) -> [Dimension] -> [Dimension]
forall a b. (a -> b) -> [a] -> [b]
map ((Dimension
width' Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
+) (Dimension -> Dimension)
-> (Dimension -> Dimension) -> Dimension -> Dimension
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. (Dimension -> Dimension -> Dimension
forall a. Integral a => a -> a -> a
`div` Dimension
2) (Dimension -> Dimension)
-> (Dimension -> Dimension) -> Dimension -> Dimension
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. (Dimension
maxw Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
-)) [Dimension]
ws
        in
        (Dimension -> Dimension -> (Dimension, Dimension) -> Rectangle)
-> [Dimension]
-> [Dimension]
-> [(Dimension, Dimension)]
-> [Rectangle]
forall a b c d. (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3 (\Dimension
x Dimension
y (Dimension
w, Dimension
h) -> Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle (Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
x) (Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
y) Dimension
w Dimension
h) [Dimension]
xs [Dimension]
ys [(Dimension, Dimension)]
c' [Rectangle] -> [Rectangle] -> [Rectangle]
forall a. [a] -> [a] -> [a]
++ Dimension
-> Dimension
-> [[(Dimension, Dimension) -> (Dimension, Dimension)]]
-> [Rectangle]
doR Dimension
width' (Dimension
n Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
1) [[(Dimension, Dimension) -> (Dimension, Dimension)]]
cs

-- | The internal function for computing the grid layout.
arrange :: Double -> Bool -> Rectangle -> [Window] -> X [(Window, Rectangle)]
arrange :: Double -> Bool -> Rectangle -> [Window] -> X [(Window, Rectangle)]
arrange Double
aspectRatio Bool
mirror (Rectangle Position
rx Position
ry Dimension
rw Dimension
rh) [Window]
wins = do
    [(Dimension, Dimension) -> (Dimension, Dimension)]
proto <- (Window -> X ((Dimension, Dimension) -> (Dimension, Dimension)))
-> [Window] -> X [(Dimension, Dimension) -> (Dimension, Dimension)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Window -> X ((Dimension, Dimension) -> (Dimension, Dimension))
mkAdjust [Window]
wins
    let
        adjs :: [(Dimension, Dimension) -> (Dimension, Dimension)]
adjs = (((Dimension, Dimension) -> (Dimension, Dimension))
 -> (Dimension, Dimension) -> (Dimension, Dimension))
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Dimension, Dimension) -> (Dimension, Dimension)
f -> (Dimension, Dimension) -> (Dimension, Dimension)
forall {a}. (a, a) -> (a, a)
twist ((Dimension, Dimension) -> (Dimension, Dimension))
-> ((Dimension, Dimension) -> (Dimension, Dimension))
-> (Dimension, Dimension)
-> (Dimension, Dimension)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. (Dimension, Dimension) -> (Dimension, Dimension)
f ((Dimension, Dimension) -> (Dimension, Dimension))
-> ((Dimension, Dimension) -> (Dimension, Dimension))
-> (Dimension, Dimension)
-> (Dimension, Dimension)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. (Dimension, Dimension) -> (Dimension, Dimension)
forall {a}. (a, a) -> (a, a)
twist) [(Dimension, Dimension) -> (Dimension, Dimension)]
proto
        rs :: [Rectangle]
rs = Double
-> (Dimension, Dimension)
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> [Rectangle]
arrange' Double
aspectRatio ((Dimension, Dimension) -> (Dimension, Dimension)
forall {a}. (a, a) -> (a, a)
twist (Dimension
rw, Dimension
rh)) [(Dimension, Dimension) -> (Dimension, Dimension)]
adjs
        rs' :: [Rectangle]
rs' = (Rectangle -> Rectangle) -> [Rectangle] -> [Rectangle]
forall a b. (a -> b) -> [a] -> [b]
map (\(Rectangle Position
x Position
y Dimension
w Dimension
h) -> (Dimension -> Dimension -> Rectangle)
-> (Dimension, Dimension) -> Rectangle
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((Position -> Position -> Dimension -> Dimension -> Rectangle)
-> (Position, Position) -> Dimension -> Dimension -> Rectangle
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle ((Position, Position) -> (Position, Position)
forall {a}. (a, a) -> (a, a)
twist (Position
x, Position
y))) ((Dimension, Dimension) -> (Dimension, Dimension)
forall {a}. (a, a) -> (a, a)
twist (Dimension
w, Dimension
h))) [Rectangle]
rs
    [(Window, Rectangle)] -> X [(Window, Rectangle)]
forall a. a -> X a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Window, Rectangle)] -> X [(Window, Rectangle)])
-> ([Rectangle] -> [(Window, Rectangle)])
-> [Rectangle]
-> X [(Window, Rectangle)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. [Window] -> [Rectangle] -> [(Window, Rectangle)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Window]
wins ([Rectangle] -> [(Window, Rectangle)])
-> ([Rectangle] -> [Rectangle])
-> [Rectangle]
-> [(Window, Rectangle)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. (Rectangle -> Rectangle) -> [Rectangle] -> [Rectangle]
forall a b. (a -> b) -> [a] -> [b]
map (\Rectangle
r -> Rectangle
r{ rect_x = rect_x r + rx, rect_y = rect_y r + ry }) ([Rectangle] -> X [(Window, Rectangle)])
-> [Rectangle] -> X [(Window, Rectangle)]
forall a b. (a -> b) -> a -> b
$ [Rectangle]
rs'
    where
    twist :: (a, a) -> (a, a)
twist
        | Bool
mirror = \(a
a, a
b) -> (a
b, a
a)
        | Bool
otherwise = (a, a) -> (a, a)
forall a. a -> a
id

arrange' :: Double -> D -> [D -> D] -> [Rectangle]
arrange' :: Double
-> (Dimension, Dimension)
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> [Rectangle]
arrange' Double
aspectRatio (Dimension
rw, Dimension
rh) [(Dimension, Dimension) -> (Dimension, Dimension)]
adjs = [Rectangle] -> [Rectangle]
forall a. [a] -> [a]
reverse ([Rectangle] -> [Rectangle]) -> [Rectangle] -> [Rectangle]
forall a b. (a -> b) -> a -> b
$ Dimension
-> Dimension
-> Dimension
-> [[(Dimension, Dimension) -> (Dimension, Dimension)]]
-> [Rectangle]
doRect Dimension
rh Dimension
rw (Int -> Dimension
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ncolumns) ([[(Dimension, Dimension) -> (Dimension, Dimension)]]
ecols [[(Dimension, Dimension) -> (Dimension, Dimension)]]
-> [[(Dimension, Dimension) -> (Dimension, Dimension)]]
-> [[(Dimension, Dimension) -> (Dimension, Dimension)]]
forall a. [a] -> [a] -> [a]
++ [[(Dimension, Dimension) -> (Dimension, Dimension)]]
cols)
    where
    nwindows :: Int
nwindows = [(Dimension, Dimension) -> (Dimension, Dimension)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Dimension, Dimension) -> (Dimension, Dimension)]
adjs
    ncolumns :: Int
ncolumns = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> (Double -> Int) -> Double -> Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Double -> Int) -> (Double -> Double) -> Double -> Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
. Double -> Double
forall a. Floating a => a -> a
sqrt (Double -> Int) -> Double -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
nwindows Double -> Double -> Double
forall a. Num a => a -> a -> a
* Dimension -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
rw Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Dimension -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
rh Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
aspectRatio)
    nrows :: Int
nrows = Int
nwindows Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
ncolumns
    nextras :: Int
nextras = Int
nwindows Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
ncolumns Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
nrows
    ([[(Dimension, Dimension) -> (Dimension, Dimension)]]
ecols, [(Dimension, Dimension) -> (Dimension, Dimension)]
adjs') = Int
-> ([(Dimension, Dimension) -> (Dimension, Dimension)]
    -> ([(Dimension, Dimension) -> (Dimension, Dimension)],
        [(Dimension, Dimension) -> (Dimension, Dimension)]))
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> ([[(Dimension, Dimension) -> (Dimension, Dimension)]],
    [(Dimension, Dimension) -> (Dimension, Dimension)])
forall a b. Int -> (a -> (b, a)) -> a -> ([b], a)
replicateS Int
nextras (Int
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> ([(Dimension, Dimension) -> (Dimension, Dimension)],
    [(Dimension, Dimension) -> (Dimension, Dimension)])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
nrows Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)) ([(Dimension, Dimension) -> (Dimension, Dimension)]
 -> ([[(Dimension, Dimension) -> (Dimension, Dimension)]],
     [(Dimension, Dimension) -> (Dimension, Dimension)]))
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> ([[(Dimension, Dimension) -> (Dimension, Dimension)]],
    [(Dimension, Dimension) -> (Dimension, Dimension)])
forall a b. (a -> b) -> a -> b
$ [(Dimension, Dimension) -> (Dimension, Dimension)]
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
forall a. [a] -> [a]
reverse [(Dimension, Dimension) -> (Dimension, Dimension)]
adjs
    ([[(Dimension, Dimension) -> (Dimension, Dimension)]]
cols, [(Dimension, Dimension) -> (Dimension, Dimension)]
_) = Int
-> ([(Dimension, Dimension) -> (Dimension, Dimension)]
    -> ([(Dimension, Dimension) -> (Dimension, Dimension)],
        [(Dimension, Dimension) -> (Dimension, Dimension)]))
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> ([[(Dimension, Dimension) -> (Dimension, Dimension)]],
    [(Dimension, Dimension) -> (Dimension, Dimension)])
forall a b. Int -> (a -> (b, a)) -> a -> ([b], a)
replicateS (Int
ncolumns Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
nextras) (Int
-> [(Dimension, Dimension) -> (Dimension, Dimension)]
-> ([(Dimension, Dimension) -> (Dimension, Dimension)],
    [(Dimension, Dimension) -> (Dimension, Dimension)])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
nrows) [(Dimension, Dimension) -> (Dimension, Dimension)]
adjs'