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

-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Layout.ResizableThreeColumns
-- Description :  Like "XMonad.Layout.ThreeColumns", but allows resizing.
-- Copyright   :  (c) Sam Tay <sam.chong.tay@gmail.com>
-- License     :  BSD3-style (see LICENSE)
--
-- Maintainer  :  ?
-- Stability   :  unstable
-- Portability :  unportable
--
-- A layout similar to tall but with three columns. With 2560x1600 pixels this
-- layout can be used for a huge main window and up to six reasonable sized
-- resizable stack windows.
-----------------------------------------------------------------------------

module XMonad.Layout.ResizableThreeColumns (
                              -- * Usage
                              -- $usage
                              ResizableThreeCol(..), MirrorResize(..)
                             ) where

import XMonad hiding (splitVertically)
import XMonad.Prelude
import XMonad.Layout.ResizableTile(MirrorResize(..))
import qualified XMonad.StackSet as W

import qualified Data.Map as M
import Data.Ratio

-- $usage
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Layout.ResizableThreeColumns
--
-- Then edit your @layoutHook@ by adding the ResizableThreeCol layout:
--
-- > myLayout = ResizableThreeCol 1 (3/100) (1/2) [] ||| ResizableThreeColMid 1 (3/100) (1/2) [] ||| etc..
-- > main = xmonad def { layoutHook = myLayout }
--
-- The first argument specifies how many windows initially appear in the main
-- window. The second argument argument specifies the amount to resize while
-- resizing and the third argument specifies the initial size of the columns.
-- A positive size designates the fraction of the screen that the main window
-- should occupy, but if the size is negative the absolute value designates the
-- fraction a stack column should occupy. If both stack columns are visible,
-- they always occupy the same amount of space.
--
-- You may also want to add the following key bindings:
--
-- > , ((modm,               xK_a), sendMessage MirrorShrink)
-- > , ((modm,               xK_z), sendMessage MirrorExpand)
--
-- The ResizableThreeColMid variant places the main window between the stack columns.
--
-- 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".


-- | Arguments are nmaster, delta, fraction
data ResizableThreeCol a
  = ResizableThreeColMid
    { forall a. ResizableThreeCol a -> Int
threeColNMaster :: !Int
    , forall a. ResizableThreeCol a -> Rational
threeColDelta :: !Rational
    , forall a. ResizableThreeCol a -> Rational
threeColFrac :: !Rational
    , forall a. ResizableThreeCol a -> [Rational]
threeColSlaves :: [Rational]
    }
  | ResizableThreeCol
    { threeColNMaster :: !Int
    , threeColDelta :: !Rational
    , threeColFrac :: !Rational
    , threeColSlaves :: [Rational]
    } deriving (Int -> ResizableThreeCol a -> ShowS
[ResizableThreeCol a] -> ShowS
ResizableThreeCol a -> String
(Int -> ResizableThreeCol a -> ShowS)
-> (ResizableThreeCol a -> String)
-> ([ResizableThreeCol a] -> ShowS)
-> Show (ResizableThreeCol a)
forall a. Int -> ResizableThreeCol a -> ShowS
forall a. [ResizableThreeCol a] -> ShowS
forall a. ResizableThreeCol a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Int -> ResizableThreeCol a -> ShowS
showsPrec :: Int -> ResizableThreeCol a -> ShowS
$cshow :: forall a. ResizableThreeCol a -> String
show :: ResizableThreeCol a -> String
$cshowList :: forall a. [ResizableThreeCol a] -> ShowS
showList :: [ResizableThreeCol a] -> ShowS
Show,ReadPrec [ResizableThreeCol a]
ReadPrec (ResizableThreeCol a)
Int -> ReadS (ResizableThreeCol a)
ReadS [ResizableThreeCol a]
(Int -> ReadS (ResizableThreeCol a))
-> ReadS [ResizableThreeCol a]
-> ReadPrec (ResizableThreeCol a)
-> ReadPrec [ResizableThreeCol a]
-> Read (ResizableThreeCol a)
forall a. ReadPrec [ResizableThreeCol a]
forall a. ReadPrec (ResizableThreeCol a)
forall a. Int -> ReadS (ResizableThreeCol a)
forall a. ReadS [ResizableThreeCol a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: forall a. Int -> ReadS (ResizableThreeCol a)
readsPrec :: Int -> ReadS (ResizableThreeCol a)
$creadList :: forall a. ReadS [ResizableThreeCol a]
readList :: ReadS [ResizableThreeCol a]
$creadPrec :: forall a. ReadPrec (ResizableThreeCol a)
readPrec :: ReadPrec (ResizableThreeCol a)
$creadListPrec :: forall a. ReadPrec [ResizableThreeCol a]
readListPrec :: ReadPrec [ResizableThreeCol a]
Read)

instance LayoutClass ResizableThreeCol a where
  doLayout :: ResizableThreeCol a
-> Rectangle
-> Stack a
-> X ([(a, Rectangle)], Maybe (ResizableThreeCol a))
doLayout (ResizableThreeCol Int
n Rational
_ Rational
f [Rational]
mf) Rectangle
r    = Bool
-> Int
-> Rational
-> [Rational]
-> Rectangle
-> Stack a
-> X ([(a, Rectangle)], Maybe (ResizableThreeCol a))
forall a (layout :: * -> *).
Bool
-> Int
-> Rational
-> [Rational]
-> Rectangle
-> Stack a
-> X ([(a, Rectangle)], Maybe (layout a))
doL Bool
False Int
n Rational
f [Rational]
mf Rectangle
r
  doLayout (ResizableThreeColMid Int
n Rational
_ Rational
f [Rational]
mf) Rectangle
r = Bool
-> Int
-> Rational
-> [Rational]
-> Rectangle
-> Stack a
-> X ([(a, Rectangle)], Maybe (ResizableThreeCol a))
forall a (layout :: * -> *).
Bool
-> Int
-> Rational
-> [Rational]
-> Rectangle
-> Stack a
-> X ([(a, Rectangle)], Maybe (layout a))
doL Bool
True  Int
n Rational
f [Rational]
mf Rectangle
r
  handleMessage :: ResizableThreeCol a
-> SomeMessage -> X (Maybe (ResizableThreeCol a))
handleMessage ResizableThreeCol a
l SomeMessage
m = 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
<$> (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
    [Window]
fs <- Map Window RationalRect -> [Window]
forall k a. Map k a -> [k]
M.keys (Map Window RationalRect -> [Window])
-> (StackSet String (Layout Window) Window ScreenId ScreenDetail
    -> Map Window RationalRect)
-> StackSet String (Layout Window) Window ScreenId ScreenDetail
-> [Window]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StackSet String (Layout Window) Window ScreenId ScreenDetail
-> Map Window RationalRect
forall i l a sid sd. StackSet i l a sid sd -> Map a RationalRect
W.floating (StackSet String (Layout Window) Window ScreenId ScreenDetail
 -> [Window])
-> X (StackSet String (Layout Window) Window ScreenId ScreenDetail)
-> X [Window]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (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
    Maybe (ResizableThreeCol a) -> X (Maybe (ResizableThreeCol a))
forall a. a -> X a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (ResizableThreeCol a) -> X (Maybe (ResizableThreeCol a)))
-> Maybe (ResizableThreeCol a) -> X (Maybe (ResizableThreeCol a))
forall a b. (a -> b) -> a -> b
$ do
      Stack Window
s <- Maybe (Stack Window)
ms
      -- make sure current stack isn't floating
      Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Stack Window -> Window
forall a. Stack a -> a
W.focus Stack Window
s Window -> [Window] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Window]
fs)
      -- remove floating windows from stack
      let s' :: Stack Window
s' = Stack Window
s { W.up = W.up s \\ fs, W.down = W.down s \\ fs }
      -- handle messages
      [Maybe (ResizableThreeCol a)] -> Maybe (ResizableThreeCol a)
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, MonadPlus m) =>
t (m a) -> m a
msum [ (Resize -> ResizableThreeCol a)
-> Maybe Resize -> Maybe (ResizableThreeCol a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Resize -> ResizableThreeCol a
forall {a}. Resize -> ResizableThreeCol a
resize       (SomeMessage -> Maybe Resize
forall m. Message m => SomeMessage -> Maybe m
fromMessage SomeMessage
m)
           , (MirrorResize -> ResizableThreeCol a)
-> Maybe MirrorResize -> Maybe (ResizableThreeCol a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Stack Window -> MirrorResize -> ResizableThreeCol a
forall {a} {a}. Stack a -> MirrorResize -> ResizableThreeCol a
mresize Stack Window
s') (SomeMessage -> Maybe MirrorResize
forall m. Message m => SomeMessage -> Maybe m
fromMessage SomeMessage
m)
           , (IncMasterN -> ResizableThreeCol a)
-> Maybe IncMasterN -> Maybe (ResizableThreeCol a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IncMasterN -> ResizableThreeCol a
forall {a}. IncMasterN -> ResizableThreeCol a
incmastern   (SomeMessage -> Maybe IncMasterN
forall m. Message m => SomeMessage -> Maybe m
fromMessage SomeMessage
m)
           ]
    where
      resize :: Resize -> ResizableThreeCol a
resize Resize
Shrink = ResizableThreeCol a
l { threeColFrac = max (-0.5) $ frac-delta }
      resize Resize
Expand = ResizableThreeCol a
l { threeColFrac = min 1 $ frac+delta }
      mresize :: Stack a -> MirrorResize -> ResizableThreeCol a
mresize Stack a
s MirrorResize
MirrorShrink = Stack a -> Rational -> ResizableThreeCol a
forall {a} {a}. Stack a -> Rational -> ResizableThreeCol a
mresize' Stack a
s Rational
delta
      mresize Stack a
s MirrorResize
MirrorExpand = Stack a -> Rational -> ResizableThreeCol a
forall {a} {a}. Stack a -> Rational -> ResizableThreeCol a
mresize' Stack a
s (Rational -> Rational
forall a. Num a => a -> a
negate Rational
delta)
      mresize' :: Stack a -> Rational -> ResizableThreeCol a
mresize' Stack a
s Rational
delt =
        let up :: Int
up = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([a] -> Int) -> [a] -> Int
forall a b. (a -> b) -> a -> b
$ Stack a -> [a]
forall a. Stack a -> [a]
W.up Stack a
s
            down :: Int
down = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([a] -> Int) -> [a] -> Int
forall a b. (a -> b) -> a -> b
$ Stack a -> [a]
forall a. Stack a -> [a]
W.down Stack a
s
            total :: Int
total = Int
up Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
down Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
            pos :: Int
pos = if Int
up Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
nmaster Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1           -- upper right
                  Bool -> Bool -> Bool
|| Int
up Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
total Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1             -- upper left
                  Bool -> Bool -> Bool
|| Int
up Int -> [Int] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int
down, Int
down Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1]  -- lower right
                  then Int
up Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
                  else Int
up
            mfrac' :: [Rational]
mfrac' = [Rational] -> Rational -> Int -> [Rational]
forall {t} {t}. (Eq t, Num t, Num t) => [t] -> t -> t -> [t]
modifymfrac ([Rational]
mfrac [Rational] -> [Rational] -> [Rational]
forall a. [a] -> [a] -> [a]
++ Rational -> [Rational]
forall a. a -> [a]
repeat Rational
1) Rational
delt Int
pos
        in ResizableThreeCol a
l { threeColSlaves = take total mfrac'}
      modifymfrac :: [t] -> t -> t -> [t]
modifymfrac [] t
_ t
_ = []
      modifymfrac (t
f:[t]
fx) t
d t
n
        | t
n t -> t -> Bool
forall a. Eq a => a -> a -> Bool
== t
0    = t
ft -> t -> t
forall a. Num a => a -> a -> a
+t
d t -> [t] -> [t]
forall a. a -> [a] -> [a]
: [t]
fx
        | Bool
otherwise = t
f t -> [t] -> [t]
forall a. a -> [a] -> [a]
: [t] -> t -> t -> [t]
modifymfrac [t]
fx t
d (t
nt -> t -> t
forall a. Num a => a -> a -> a
-t
1)
      incmastern :: IncMasterN -> ResizableThreeCol a
incmastern (IncMasterN Int
x) = ResizableThreeCol a
l { threeColNMaster = max 0 (nmaster+x) }
      nmaster :: Int
nmaster = ResizableThreeCol a -> Int
forall a. ResizableThreeCol a -> Int
threeColNMaster ResizableThreeCol a
l
      delta :: Rational
delta = ResizableThreeCol a -> Rational
forall a. ResizableThreeCol a -> Rational
threeColDelta ResizableThreeCol a
l
      frac :: Rational
frac = ResizableThreeCol a -> Rational
forall a. ResizableThreeCol a -> Rational
threeColFrac ResizableThreeCol a
l
      mfrac :: [Rational]
mfrac = ResizableThreeCol a -> [Rational]
forall a. ResizableThreeCol a -> [Rational]
threeColSlaves ResizableThreeCol a
l
  description :: ResizableThreeCol a -> String
description ResizableThreeCol a
_ = String
"ResizableThreeCol"

doL :: Bool -> Int -> Rational -> [Rational] -> Rectangle
    -> W.Stack a -> X ([(a, Rectangle)], Maybe (layout a))
doL :: forall a (layout :: * -> *).
Bool
-> Int
-> Rational
-> [Rational]
-> Rectangle
-> Stack a
-> X ([(a, Rectangle)], Maybe (layout a))
doL Bool
middle Int
nmaster Rational
f [Rational]
mf Rectangle
r =
  ([(a, Rectangle)], Maybe (layout a))
-> X ([(a, Rectangle)], Maybe (layout a))
forall a. a -> X a
forall (m :: * -> *) a. Monad m => a -> m a
return
  (([(a, Rectangle)], Maybe (layout a))
 -> X ([(a, Rectangle)], Maybe (layout a)))
-> (Stack a -> ([(a, Rectangle)], Maybe (layout a)))
-> Stack a
-> X ([(a, Rectangle)], Maybe (layout a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (, Maybe (layout a)
forall a. Maybe a
Nothing)
  ([(a, Rectangle)] -> ([(a, Rectangle)], Maybe (layout a)))
-> (Stack a -> [(a, Rectangle)])
-> Stack a
-> ([(a, Rectangle)], Maybe (layout a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([a] -> [Rectangle] -> [(a, Rectangle)])
-> ([a] -> [Rectangle]) -> [a] -> [(a, Rectangle)]
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap [a] -> [Rectangle] -> [(a, Rectangle)]
forall a b. [a] -> [b] -> [(a, b)]
zip (Bool
-> Rational -> [Rational] -> Rectangle -> Int -> Int -> [Rectangle]
tile3 Bool
middle Rational
f ([Rational]
mf [Rational] -> [Rational] -> [Rational]
forall a. [a] -> [a] -> [a]
++ Rational -> [Rational]
forall a. a -> [a]
repeat Rational
1) Rectangle
r Int
nmaster (Int -> [Rectangle]) -> ([a] -> Int) -> [a] -> [Rectangle]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length) ([a] -> [(a, Rectangle)])
-> (Stack a -> [a]) -> Stack a -> [(a, Rectangle)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stack a -> [a]
forall a. Stack a -> [a]
W.integrate

-- | tile3.  Compute window positions using 3 panes
tile3 :: Bool -> Rational -> [Rational] -> Rectangle -> Int -> Int -> [Rectangle]
tile3 :: Bool
-> Rational -> [Rational] -> Rectangle -> Int -> Int -> [Rectangle]
tile3 Bool
middle Rational
f [Rational]
mf Rectangle
r Int
nmaster Int
n
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
nmaster Bool -> Bool -> Bool
|| Int
nmaster Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = [Rational] -> Int -> Rectangle -> [Rectangle]
forall r. RealFrac r => [r] -> Int -> Rectangle -> [Rectangle]
splitVertically [Rational]
mf Int
n Rectangle
r
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
nmasterInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 = [Rational] -> Int -> Rectangle -> [Rectangle]
forall r. RealFrac r => [r] -> Int -> Rectangle -> [Rectangle]
splitVertically [Rational]
mf Int
nmaster Rectangle
s1
                  [Rectangle] -> [Rectangle] -> [Rectangle]
forall a. [a] -> [a] -> [a]
++ [Rational] -> Int -> Rectangle -> [Rectangle]
forall r. RealFrac r => [r] -> Int -> Rectangle -> [Rectangle]
splitVertically (Int -> [Rational] -> [Rational]
forall a. Int -> [a] -> [a]
drop Int
nmaster [Rational]
mf) (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
nmaster) Rectangle
s2
  | Bool
otherwise = [[Rectangle]] -> [Rectangle]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [Rational] -> Int -> Rectangle -> [Rectangle]
forall r. RealFrac r => [r] -> Int -> Rectangle -> [Rectangle]
splitVertically [Rational]
mf Int
nmaster Rectangle
r1
                       , [Rational] -> Int -> Rectangle -> [Rectangle]
forall r. RealFrac r => [r] -> Int -> Rectangle -> [Rectangle]
splitVertically (Int -> [Rational] -> [Rational]
forall a. Int -> [a] -> [a]
drop Int
nmaster [Rational]
mf) Int
nstack1 Rectangle
r2
                       , [Rational] -> Int -> Rectangle -> [Rectangle]
forall r. RealFrac r => [r] -> Int -> Rectangle -> [Rectangle]
splitVertically (Int -> [Rational] -> [Rational]
forall a. Int -> [a] -> [a]
drop (Int
nmaster Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
nstack1) [Rational]
mf) Int
nstack2 Rectangle
r3
                       ]
  where
    (Rectangle
r1, Rectangle
r2, Rectangle
r3) = Bool -> Rational -> Rectangle -> (Rectangle, Rectangle, Rectangle)
split3HorizontallyBy Bool
middle (if Rational
fRational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<Rational
0 then Rational
1Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+Rational
2Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
*Rational
f else Rational
f) Rectangle
r
    (Rectangle
s1, Rectangle
s2)     = Rational -> Rectangle -> (Rectangle, Rectangle)
forall r. RealFrac r => r -> Rectangle -> (Rectangle, Rectangle)
splitHorizontallyBy (if Rational
fRational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<Rational
0 then Rational
1Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+Rational
f else Rational
f) Rectangle
r
    nstack :: Int
nstack       = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
nmaster
    nstack1 :: Int
nstack1      = Ratio Int -> Int
forall b. Integral b => Ratio Int -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Int
nstack Int -> Int -> Ratio Int
forall a. Integral a => a -> a -> Ratio a
% Int
2)
    nstack2 :: Int
nstack2      = Int
nstack Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
nstack1

splitVertically :: RealFrac r => [r] -> Int -> Rectangle -> [Rectangle]
splitVertically :: forall r. RealFrac r => [r] -> Int -> Rectangle -> [Rectangle]
splitVertically [] Int
_ Rectangle
r = [Rectangle
r]
splitVertically [r]
_ Int
n Rectangle
r | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = [Rectangle
r]
splitVertically (r
f:[r]
fx) Int
n (Rectangle Position
sx Position
sy Dimension
sw Dimension
sh) =
  let smallh :: Dimension
smallh = Dimension -> Dimension -> Dimension
forall a. Ord a => a -> a -> a
min Dimension
sh (r -> Dimension
forall b. Integral b => r -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (r -> Dimension) -> r -> Dimension
forall a b. (a -> b) -> a -> b
$ Dimension -> r
forall a b. (Integral a, Num b) => a -> b
fi (Dimension
sh Dimension -> Dimension -> Dimension
forall a. Integral a => a -> a -> a
`div` Int -> Dimension
forall a b. (Integral a, Num b) => a -> b
fi Int
n) r -> r -> r
forall a. Num a => a -> a -> a
* r
f)
  in Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle Position
sx Position
sy Dimension
sw Dimension
smallh Rectangle -> [Rectangle] -> [Rectangle]
forall a. a -> [a] -> [a]
:
       [r] -> Int -> Rectangle -> [Rectangle]
forall r. RealFrac r => [r] -> Int -> Rectangle -> [Rectangle]
splitVertically [r]
fx (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle Position
sx (Position
syPosition -> Position -> Position
forall a. Num a => a -> a -> a
+Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fi Dimension
smallh) Dimension
sw (Dimension
shDimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
-Dimension
smallh))

split3HorizontallyBy :: Bool -> Rational -> Rectangle -> (Rectangle, Rectangle, Rectangle)
split3HorizontallyBy :: Bool -> Rational -> Rectangle -> (Rectangle, Rectangle, Rectangle)
split3HorizontallyBy Bool
middle Rational
f (Rectangle Position
sx Position
sy Dimension
sw Dimension
sh) =
  if Bool
middle
  then ( Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle (Position
sx Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
r3w) Position
sy Dimension
r1w Dimension
sh
       , Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle (Position
sx Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
r3w Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
r1w) Position
sy Dimension
r2w Dimension
sh
       , Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle Position
sx Position
sy Dimension
r3w Dimension
sh )
  else ( Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle Position
sx Position
sy Dimension
r1w Dimension
sh
       , Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle (Position
sx Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
r1w) Position
sy Dimension
r2w Dimension
sh
       , Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle (Position
sx Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
r1w Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
r2w) Position
sy Dimension
r3w Dimension
sh )
  where
    r1w :: Dimension
r1w = Rational -> Dimension
forall b. Integral b => Rational -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Rational -> Dimension) -> Rational -> Dimension
forall a b. (a -> b) -> a -> b
$ Dimension -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
sw Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
f
    r2w :: Dimension
r2w = Ratio Dimension -> Dimension
forall b. Integral b => Ratio Dimension -> b
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Ratio Dimension -> Dimension) -> Ratio Dimension -> Dimension
forall a b. (a -> b) -> a -> b
$ (Dimension
sw Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
r1w) Dimension -> Dimension -> Ratio Dimension
forall a. Integral a => a -> a -> Ratio a
% Dimension
2
    r3w :: Dimension
r3w = Dimension
sw Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
r1w Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
r2w