{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Layout.CircleEx
-- Description :  An elliptical, overlapping layout—extended version.
-- Copyright   :  (c) Peter De Wachter, Ilya V. Portnov
-- License     :  BSD-style (see LICENSE)
--
-- Maintainer  :  Ilya V. Portnov <portnov84@rambler.ru>
-- Stability   :  unstable
-- Portability :  unportable
--
-- Circle is an elliptical, overlapping layout. Original code by Peter De Wachter,
-- extended by Ilya Porntov.
-----------------------------------------------------------------------------

module XMonad.Layout.CircleEx (
    -- * Usage
    -- $usage
    CircleEx (..), circle, circleEx,
    CircleExMsg (..)
  )
  where

import Data.Ratio

import XMonad
import XMonad.StackSet (Stack)
import XMonad.Prelude
import qualified XMonad.StackSet as W

-- $usage
--
-- The layout puts the first N windows (called master) into the center of
-- screen. All others (called secondary, or stack) are organized in a circle
-- (well, ellipse). When opening a new secondary window, its size will be
-- slightly smaller than that of its predecessor (this is configurable). If
-- the number of master windows is set to zero, all windows will be arranged
-- in a circle. If there is more than one master window, they will be stacked
-- in the center on top of each other. The size of each additional master
-- window will again be slightly smaller than that of the former.
--
-- Since a picture says more than a thousand words, you see one
-- <https://github.com/xmonad/xmonad-contrib/assets/50166980/90ef1273-5201-4380-8b94-9e62d3c98e1c here>.
--
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Layout.CircleEx
--
-- Then edit your @layoutHook@ by adding the 'CircleEx' layout:
--
-- > myCircle = circleEx {cDelta = -3*pi/4}
-- > myLayout = myCircle ||| Full ||| etc..
-- > main = xmonad def { layoutHook = myLayout }
--
-- This layout understands standard messages:
--
-- * 'IncMasterN': increase or decrease the number of master windows.
-- * 'Shrink' and 'Expand': change the size of master windows.
--
-- More layout-specific messages are also supported, see 'CircleExMsg' below.
--
-- For more detailed instructions on editing the layoutHook see:
-- "XMonad.Doc.Extending#Editing_the_layout_hook"

-- | The layout data type. It is recommended to not use the 'CircleEx' data
-- constructor directly, and instead rely on record update syntax; for
-- example: @circleEx {cMasterRatio = 4%5}@. In this way you can avoid nasty
-- surprises if one day additional fields are added to @CircleEx@.
data CircleEx a = CircleEx
    { forall a. CircleEx a -> Int
cNMaster :: !Int          -- ^ Number of master windows. Default value is 1.
    , forall a. CircleEx a -> Rational
cMasterRatio :: !Rational -- ^ Size of master window in relation to screen size.
                                --   Default value is @4%5@.
    , forall a. CircleEx a -> Rational
cStackRatio :: !Rational  -- ^ Size of first secondary window in relation to screen size.
                                --   Default value is @3%5@.
    , forall a. CircleEx a -> Rational
cMultiplier :: !Rational  -- ^ Coefficient used to calculate the sizes of subsequent secondary
                                --   windows. The size of the next window is calculated as the
                                --   size of the previous one multiplied by this value.
                                --   This value is also used to scale master windows, in case
                                --   there is more than one.
                                --   Default value is @5%6@. Set this to 1 if you want all secondary
                                --   windows to have the same size.
    , forall a. CircleEx a -> Double
cDelta :: !Double         -- ^ Angle of rotation of the whole circle layout. Usual values
                                --   are from 0 to 2π, although it will work outside
                                --   this range as well. Default value of 0 means that the first
                                --   secondary window will be placed at the right side of screen.
    } deriving (CircleEx a -> CircleEx a -> Bool
(CircleEx a -> CircleEx a -> Bool)
-> (CircleEx a -> CircleEx a -> Bool) -> Eq (CircleEx a)
forall a. CircleEx a -> CircleEx a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. CircleEx a -> CircleEx a -> Bool
== :: CircleEx a -> CircleEx a -> Bool
$c/= :: forall a. CircleEx a -> CircleEx a -> Bool
/= :: CircleEx a -> CircleEx a -> Bool
Eq, Int -> CircleEx a -> ShowS
[CircleEx a] -> ShowS
CircleEx a -> String
(Int -> CircleEx a -> ShowS)
-> (CircleEx a -> String)
-> ([CircleEx a] -> ShowS)
-> Show (CircleEx a)
forall a. Int -> CircleEx a -> ShowS
forall a. [CircleEx a] -> ShowS
forall a. CircleEx a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Int -> CircleEx a -> ShowS
showsPrec :: Int -> CircleEx a -> ShowS
$cshow :: forall a. CircleEx a -> String
show :: CircleEx a -> String
$cshowList :: forall a. [CircleEx a] -> ShowS
showList :: [CircleEx a] -> ShowS
Show, ReadPrec [CircleEx a]
ReadPrec (CircleEx a)
Int -> ReadS (CircleEx a)
ReadS [CircleEx a]
(Int -> ReadS (CircleEx a))
-> ReadS [CircleEx a]
-> ReadPrec (CircleEx a)
-> ReadPrec [CircleEx a]
-> Read (CircleEx a)
forall a. ReadPrec [CircleEx a]
forall a. ReadPrec (CircleEx a)
forall a. Int -> ReadS (CircleEx a)
forall a. ReadS [CircleEx a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: forall a. Int -> ReadS (CircleEx a)
readsPrec :: Int -> ReadS (CircleEx a)
$creadList :: forall a. ReadS [CircleEx a]
readList :: ReadS [CircleEx a]
$creadPrec :: forall a. ReadPrec (CircleEx a)
readPrec :: ReadPrec (CircleEx a)
$creadListPrec :: forall a. ReadPrec [CircleEx a]
readListPrec :: ReadPrec [CircleEx a]
Read)

-- | Circle layout with default settings:
--
-- * Number of master windows is set to 1
-- * @cMasterRatio@ is set to @70/99@, which is nearly @1/sqrt(2)@
-- * @cStackRatio@ is set to @2/5@
-- * @cMultiplier@ is set to 1, which means all secondary windows
--   will have the same size
--
-- This can be used as a drop-in replacement for "XMonad.Layout.Circle".
circle :: CircleEx a
circle :: forall a. CircleEx a
circle = Int -> Rational -> Rational -> Rational -> Double -> CircleEx a
forall a.
Int -> Rational -> Rational -> Rational -> Double -> CircleEx a
CircleEx Int
1 (Integer
70Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
%Integer
99) (Integer
2Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
%Integer
5) Rational
1 Double
0

-- | Another variant of default settings for circle layout:
--
-- * Number of master windows is set to 1
-- * @cMasterRatio@ is set to @4/5@
-- * @cStackRatio@ is set to @3/5@
-- * @cMultiplier@ is set to @5/6@
--
circleEx :: CircleEx a
circleEx :: forall a. CircleEx a
circleEx = Int -> Rational -> Rational -> Rational -> Double -> CircleEx a
forall a.
Int -> Rational -> Rational -> Rational -> Double -> CircleEx a
CircleEx Int
1 (Integer
4Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
%Integer
5) (Integer
3Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
%Integer
5) (Integer
5Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
%Integer
6) Double
0

-- | Specific messages understood by CircleEx layout.
data CircleExMsg
  = Rotate !Double            -- ^ Rotate secondary windows by specific angle
  | IncStackRatio !Rational   -- ^ Increase (or decrease, with negative value) sizes of secondary windows
  | IncMultiplier !Rational   -- ^ Increase 'cMultiplier'.
  deriving (CircleExMsg -> CircleExMsg -> Bool
(CircleExMsg -> CircleExMsg -> Bool)
-> (CircleExMsg -> CircleExMsg -> Bool) -> Eq CircleExMsg
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CircleExMsg -> CircleExMsg -> Bool
== :: CircleExMsg -> CircleExMsg -> Bool
$c/= :: CircleExMsg -> CircleExMsg -> Bool
/= :: CircleExMsg -> CircleExMsg -> Bool
Eq, Int -> CircleExMsg -> ShowS
[CircleExMsg] -> ShowS
CircleExMsg -> String
(Int -> CircleExMsg -> ShowS)
-> (CircleExMsg -> String)
-> ([CircleExMsg] -> ShowS)
-> Show CircleExMsg
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CircleExMsg -> ShowS
showsPrec :: Int -> CircleExMsg -> ShowS
$cshow :: CircleExMsg -> String
show :: CircleExMsg -> String
$cshowList :: [CircleExMsg] -> ShowS
showList :: [CircleExMsg] -> ShowS
Show, Typeable)

instance Message CircleExMsg

instance LayoutClass CircleEx Window where
  doLayout :: CircleEx Window -> Rectangle -> Stack Window -> X ([(Window, Rectangle)], Maybe (CircleEx Window))
  doLayout :: CircleEx Window
-> Rectangle
-> Stack Window
-> X ([(Window, Rectangle)], Maybe (CircleEx Window))
doLayout CircleEx Window
layout Rectangle
rect Stack Window
stack = do
    [(Window, Rectangle)]
result <- [(Window, Rectangle)] -> X [(Window, Rectangle)]
raiseFocus ([(Window, Rectangle)] -> X [(Window, Rectangle)])
-> [(Window, Rectangle)] -> X [(Window, Rectangle)]
forall a b. (a -> b) -> a -> b
$ CircleEx Window -> Rectangle -> [Window] -> [(Window, Rectangle)]
forall a. CircleEx a -> Rectangle -> [a] -> [(a, Rectangle)]
circleLayout CircleEx Window
layout Rectangle
rect ([Window] -> [(Window, Rectangle)])
-> [Window] -> [(Window, Rectangle)]
forall a b. (a -> b) -> a -> b
$ Stack Window -> [Window]
forall a. Stack a -> [a]
W.integrate Stack Window
stack
    ([(Window, Rectangle)], Maybe (CircleEx Window))
-> X ([(Window, Rectangle)], Maybe (CircleEx Window))
forall a. a -> X a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Window, Rectangle)]
result, Maybe (CircleEx Window)
forall a. Maybe a
Nothing)

  pureMessage :: CircleEx Window -> SomeMessage -> Maybe (CircleEx Window)
  pureMessage :: CircleEx Window -> SomeMessage -> Maybe (CircleEx Window)
pureMessage CircleEx Window
layout SomeMessage
m =
      [Maybe (CircleEx Window)] -> Maybe (CircleEx Window)
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, MonadPlus m) =>
t (m a) -> m a
msum [IncMasterN -> CircleEx Window
forall a. IncMasterN -> CircleEx a
changeMasterN (IncMasterN -> CircleEx Window)
-> Maybe IncMasterN -> Maybe (CircleEx Window)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SomeMessage -> Maybe IncMasterN
forall m. Message m => SomeMessage -> Maybe m
fromMessage SomeMessage
m,
            Resize -> CircleEx Window
forall a. Resize -> CircleEx a
resize (Resize -> CircleEx Window)
-> Maybe Resize -> Maybe (CircleEx Window)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SomeMessage -> Maybe Resize
forall m. Message m => SomeMessage -> Maybe m
fromMessage SomeMessage
m,
            CircleExMsg -> CircleEx Window
forall a. CircleExMsg -> CircleEx a
specific (CircleExMsg -> CircleEx Window)
-> Maybe CircleExMsg -> Maybe (CircleEx Window)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SomeMessage -> Maybe CircleExMsg
forall m. Message m => SomeMessage -> Maybe m
fromMessage SomeMessage
m]
    where
      deltaSize :: Rational
deltaSize = Integer
11 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
10

      resize :: Resize -> CircleEx a
      resize :: forall a. Resize -> CircleEx a
resize Resize
Shrink = CircleEx Window
layout {cMasterRatio = max 0.1 $ min 1.0 $ cMasterRatio layout / deltaSize}
      resize Resize
Expand = CircleEx Window
layout {cMasterRatio = max 0.1 $ min 1.0 $ cMasterRatio layout * deltaSize}

      changeMasterN :: IncMasterN -> CircleEx a
      changeMasterN :: forall a. IncMasterN -> CircleEx a
changeMasterN (IncMasterN Int
d) = CircleEx Window
layout {cNMaster = max 0 (cNMaster layout + d)}

      specific :: CircleExMsg -> CircleEx a
      specific :: forall a. CircleExMsg -> CircleEx a
specific (Rotate Double
delta) = CircleEx Window
layout {cDelta = delta + cDelta layout}
      specific (IncStackRatio Rational
delta) = CircleEx Window
layout {cStackRatio = max 0.1 $ min 2.0 $ delta + cStackRatio layout}
      specific (IncMultiplier Rational
delta) = CircleEx Window
layout {cMultiplier = max 0.1 $ min 2.0 $ delta + cMultiplier layout}

circleLayout :: CircleEx a -> Rectangle -> [a] -> [(a, Rectangle)]
circleLayout :: forall a. CircleEx a -> Rectangle -> [a] -> [(a, Rectangle)]
circleLayout CircleEx a
_ Rectangle
_ [] = []
circleLayout (CircleEx {Double
Int
Rational
cNMaster :: forall a. CircleEx a -> Int
cMasterRatio :: forall a. CircleEx a -> Rational
cStackRatio :: forall a. CircleEx a -> Rational
cMultiplier :: forall a. CircleEx a -> Rational
cDelta :: forall a. CircleEx a -> Double
cNMaster :: Int
cMasterRatio :: Rational
cStackRatio :: Rational
cMultiplier :: Rational
cDelta :: Double
..}) Rectangle
rectangle [a]
wins =
    [a] -> [(a, Rectangle)]
forall a. [a] -> [(a, Rectangle)]
master (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
cNMaster [a]
wins) [(a, Rectangle)] -> [(a, Rectangle)] -> [(a, Rectangle)]
forall a. [a] -> [a] -> [a]
++ [a] -> [(a, Rectangle)]
forall a. [a] -> [(a, Rectangle)]
rest (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
cNMaster [a]
wins)
  where
    master :: [a] -> [(a, Rectangle)]
    master :: forall a. [a] -> [(a, Rectangle)]
master [a]
ws = [a] -> [Rectangle] -> [(a, Rectangle)]
forall a b. [a] -> [b] -> [(a, b)]
zip [a]
ws ([Rectangle] -> [(a, Rectangle)])
-> [Rectangle] -> [(a, Rectangle)]
forall a b. (a -> b) -> a -> b
$ (Int -> Rectangle) -> [Int] -> [Rectangle]
forall a b. (a -> b) -> [a] -> [b]
map (Rational -> Rational -> Rectangle -> Int -> Rectangle
placeCenter Rational
cMasterRatio Rational
cMultiplier Rectangle
rectangle)
                           [Int
cNMasterInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1, Int
cNMasterInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2 .. Int
0]
    rest :: [a] -> [(a, Rectangle)]
    rest :: forall a. [a] -> [(a, Rectangle)]
rest [a]
ws = [a] -> [Rectangle] -> [(a, Rectangle)]
forall a b. [a] -> [b] -> [(a, b)]
zip [a]
ws ([Rectangle] -> [(a, Rectangle)])
-> [Rectangle] -> [(a, Rectangle)]
forall a b. (a -> b) -> a -> b
$ (Double -> Int -> Rectangle) -> [Double] -> [Int] -> [Rectangle]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Rational -> Rational -> Rectangle -> Double -> Int -> Rectangle
placeSatellite Rational
cStackRatio Rational
cMultiplier Rectangle
rectangle)
                        ((Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
cDelta) [Double
0, Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
2 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
ws) ..])
                        [Int
0 ..]


raiseFocus :: [(Window, Rectangle)] -> X [(Window, Rectangle)]
raiseFocus :: [(Window, Rectangle)] -> X [(Window, Rectangle)]
raiseFocus [(Window, Rectangle)]
wrs = do
  Maybe Window
focused <- (WindowSet -> X (Maybe Window)) -> X (Maybe Window)
forall a. (WindowSet -> X a) -> X a
withWindowSet (Maybe Window -> X (Maybe Window)
forall a. a -> X a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Window -> X (Maybe Window))
-> (WindowSet -> Maybe Window) -> WindowSet -> X (Maybe Window)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WindowSet -> Maybe Window
forall i l a s sd. StackSet i l a s sd -> Maybe a
W.peek)
  [(Window, Rectangle)] -> X [(Window, Rectangle)]
forall a. a -> X a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Window, Rectangle)] -> X [(Window, Rectangle)])
-> [(Window, Rectangle)] -> X [(Window, Rectangle)]
forall a b. (a -> b) -> a -> b
$ case ((Window, Rectangle) -> Bool)
-> [(Window, Rectangle)] -> Maybe (Window, Rectangle)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((Maybe Window -> Maybe Window -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Window
focused) (Maybe Window -> Bool)
-> ((Window, Rectangle) -> Maybe Window)
-> (Window, Rectangle)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Window -> Maybe Window
forall a. a -> Maybe a
Just (Window -> Maybe Window)
-> ((Window, Rectangle) -> Window)
-> (Window, Rectangle)
-> Maybe Window
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Window, Rectangle) -> Window
forall a b. (a, b) -> a
fst) [(Window, Rectangle)]
wrs of
             Just (Window, Rectangle)
x  -> (Window, Rectangle)
x (Window, Rectangle)
-> [(Window, Rectangle)] -> [(Window, Rectangle)]
forall a. a -> [a] -> [a]
: (Window, Rectangle)
-> [(Window, Rectangle)] -> [(Window, Rectangle)]
forall a. Eq a => a -> [a] -> [a]
delete (Window, Rectangle)
x [(Window, Rectangle)]
wrs
             Maybe (Window, Rectangle)
Nothing -> [(Window, Rectangle)]
wrs

placeCenter :: Rational -> Rational -> Rectangle -> Int -> Rectangle
placeCenter :: Rational -> Rational -> Rectangle -> Int -> Rectangle
placeCenter Rational
ratio Rational
multiplier (Rectangle Position
x Position
y Dimension
width Dimension
height) Int
n = Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle Position
x' Position
y' Dimension
width' Dimension
height'
  where
    m :: Rational
m = Rational
ratio Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
multiplier Rational -> Int -> Rational
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
n
    width' :: Dimension
width' = Rational -> Dimension
forall b. Integral b => Rational -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Rational
m Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Dimension -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
width)
    height' :: Dimension
height' = Rational -> Dimension
forall b. Integral b => Rational -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Rational
m Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Dimension -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
height)
    x' :: Position
x' = Position
x Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Dimension
width Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
width') Position -> Position -> Position
forall a. Integral a => a -> a -> a
`div` Position
2
    y' :: Position
y' = Position
y Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Dimension -> Position
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Dimension
height Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
height') Position -> Position -> Position
forall a. Integral a => a -> a -> a
`div` Position
2

placeSatellite :: Rational -> Rational -> Rectangle -> Double -> Int -> Rectangle
placeSatellite :: Rational -> Rational -> Rectangle -> Double -> Int -> Rectangle
placeSatellite Rational
ratio Rational
multiplier (Rectangle Position
x Position
y Dimension
width Dimension
height) Double
alpha Int
n =
    Position -> Position -> Dimension -> Dimension -> Rectangle
Rectangle Position
x' Position
y' Dimension
width' Dimension
height'
  where
    m :: Rational
m = Rational
ratio Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
multiplier Rational -> Int -> Rational
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
n
    x' :: Position
x' = Position
x Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Double -> Position
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
rx Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
rx Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
alpha)
    y' :: Position
y' = Position
y Position -> Position -> Position
forall a. Num a => a -> a -> a
+ Double -> Position
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
ry Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
ry Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
alpha)
    rx :: Double
rx = Dimension -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Dimension
width Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
width') Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
    ry :: Double
ry = Dimension -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Dimension
height Dimension -> Dimension -> Dimension
forall a. Num a => a -> a -> a
- Dimension
height') Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
    width' :: Dimension
width' = Rational -> Dimension
forall b. Integral b => Rational -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Dimension -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
width Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
m)
    height' :: Dimension
height' = Rational -> Dimension
forall b. Integral b => Rational -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Dimension -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Dimension
height Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
m)