{-|
Module      : Monomer.Common.BasicTypes
Copyright   : (c) 2018 Francisco Vallarino
License     : BSD-3-Clause (see the LICENSE file)
Maintainer  : fjvallarino@gmail.com
Stability   : experimental
Portability : non-portable

Basic types used across the library.
-}
{-# LANGUAGE DeriveGeneric #-}

module Monomer.Common.BasicTypes where

import Data.Default
import Data.Sequence (Seq)
import GHC.Generics

import qualified Data.Sequence as Seq

-- | An index in the list of children of a widget.
type PathStep = Int
-- | A sequence of steps, usually from the root.
type Path = Seq PathStep
-- | Resize factor.
type Factor = Double

-- | Point in the 2D space.
data Point = Point {
  Point -> Double
_pX :: {-# UNPACK #-} !Double,
  Point -> Double
_pY :: {-# UNPACK #-} !Double
} deriving (Point -> Point -> Bool
(Point -> Point -> Bool) -> (Point -> Point -> Bool) -> Eq Point
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Point -> Point -> Bool
$c/= :: Point -> Point -> Bool
== :: Point -> Point -> Bool
$c== :: Point -> Point -> Bool
Eq, Int -> Point -> ShowS
[Point] -> ShowS
Point -> String
(Int -> Point -> ShowS)
-> (Point -> String) -> ([Point] -> ShowS) -> Show Point
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Point] -> ShowS
$cshowList :: [Point] -> ShowS
show :: Point -> String
$cshow :: Point -> String
showsPrec :: Int -> Point -> ShowS
$cshowsPrec :: Int -> Point -> ShowS
Show, (forall x. Point -> Rep Point x)
-> (forall x. Rep Point x -> Point) -> Generic Point
forall x. Rep Point x -> Point
forall x. Point -> Rep Point x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Point x -> Point
$cfrom :: forall x. Point -> Rep Point x
Generic)

instance Default Point where
  def :: Point
def = Double -> Double -> Point
Point Double
0 Double
0

-- | Width and height, used for size requirements.
data Size = Size {
  Size -> Double
_sW :: {-# UNPACK #-} !Double,
  Size -> Double
_sH :: {-# UNPACK #-} !Double
} deriving (Size -> Size -> Bool
(Size -> Size -> Bool) -> (Size -> Size -> Bool) -> Eq Size
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Size -> Size -> Bool
$c/= :: Size -> Size -> Bool
== :: Size -> Size -> Bool
$c== :: Size -> Size -> Bool
Eq, Int -> Size -> ShowS
[Size] -> ShowS
Size -> String
(Int -> Size -> ShowS)
-> (Size -> String) -> ([Size] -> ShowS) -> Show Size
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Size] -> ShowS
$cshowList :: [Size] -> ShowS
show :: Size -> String
$cshow :: Size -> String
showsPrec :: Int -> Size -> ShowS
$cshowsPrec :: Int -> Size -> ShowS
Show, (forall x. Size -> Rep Size x)
-> (forall x. Rep Size x -> Size) -> Generic Size
forall x. Rep Size x -> Size
forall x. Size -> Rep Size x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Size x -> Size
$cfrom :: forall x. Size -> Rep Size x
Generic)

instance Default Size where
  def :: Size
def = Double -> Double -> Size
Size Double
0 Double
0

-- | Rectangle, usually representing an area of the screen.
data Rect = Rect {
  Rect -> Double
_rX :: {-# UNPACK #-} !Double,
  Rect -> Double
_rY :: {-# UNPACK #-} !Double,
  Rect -> Double
_rW :: {-# UNPACK #-} !Double,
  Rect -> Double
_rH :: {-# UNPACK #-} !Double
} deriving (Rect -> Rect -> Bool
(Rect -> Rect -> Bool) -> (Rect -> Rect -> Bool) -> Eq Rect
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Rect -> Rect -> Bool
$c/= :: Rect -> Rect -> Bool
== :: Rect -> Rect -> Bool
$c== :: Rect -> Rect -> Bool
Eq, Int -> Rect -> ShowS
[Rect] -> ShowS
Rect -> String
(Int -> Rect -> ShowS)
-> (Rect -> String) -> ([Rect] -> ShowS) -> Show Rect
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Rect] -> ShowS
$cshowList :: [Rect] -> ShowS
show :: Rect -> String
$cshow :: Rect -> String
showsPrec :: Int -> Rect -> ShowS
$cshowsPrec :: Int -> Rect -> ShowS
Show, (forall x. Rect -> Rep Rect x)
-> (forall x. Rep Rect x -> Rect) -> Generic Rect
forall x. Rep Rect x -> Rect
forall x. Rect -> Rep Rect x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Rect x -> Rect
$cfrom :: forall x. Rect -> Rep Rect x
Generic)

instance Default Rect where
  def :: Rect
def = Double -> Double -> Double -> Double -> Rect
Rect Double
0 Double
0 Double
0 Double
0

-- | An empty path.
emptyPath :: Path
emptyPath :: Path
emptyPath = Path
forall a. Seq a
Seq.empty

-- | The path of the root element.
rootPath :: Path
rootPath :: Path
rootPath = Int -> Path
forall a. a -> Seq a
Seq.singleton Int
0

-- | Checks if a point is inside the given rect.
pointInRect :: Point -> Rect -> Bool
pointInRect :: Point -> Rect -> Bool
pointInRect (Point Double
px Double
py) Rect
rect = Double -> Rect -> Bool
coordInRectH Double
px Rect
rect Bool -> Bool -> Bool
&& Double -> Rect -> Bool
coordInRectY Double
py Rect
rect

-- | Checks if a point is inside the given ellipse.
pointInEllipse :: Point -> Rect -> Bool
pointInEllipse :: Point -> Rect -> Bool
pointInEllipse (Point Double
px Double
py) Rect
rect = Double
ellipseTest Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
1 where
  Rect Double
rx Double
ry Double
rw Double
rh = Rect
rect
  ew :: Double
ew = Double
rw Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
  eh :: Double
eh = Double
rh Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
  cx :: Double
cx = Double
rx Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
ew
  cy :: Double
cy = Double
ry Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
eh
  ellipseTest :: Double
ellipseTest = ((Double
px Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
cx) Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
ew Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2  Double -> Double -> Double
forall a. Num a => a -> a -> a
+ ((Double
py Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
cy) Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
eh Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2

-- | Adds two points.
addPoint :: Point -> Point -> Point
addPoint :: Point -> Point -> Point
addPoint (Point Double
x1 Double
y1) (Point Double
x2 Double
y2) = Double -> Double -> Point
Point (Double
x1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
x2) (Double
y1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
y2)

-- | Subtracts one point from another.
subPoint :: Point -> Point -> Point
subPoint :: Point -> Point -> Point
subPoint (Point Double
x1 Double
y1) (Point Double
x2 Double
y2) = Double -> Double -> Point
Point (Double
x1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
x2) (Double
y1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
y2)

-- | Multiplies the coordinates of a point by the given factor.
mulPoint :: Double -> Point -> Point
mulPoint :: Double -> Point -> Point
mulPoint Double
factor (Point Double
x Double
y) = Double -> Double -> Point
Point (Double
factor Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x) (Double
factor Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y)

-- | Returns the middle between two points.
midPoint :: Point -> Point -> Point
midPoint :: Point -> Point -> Point
midPoint Point
p1 Point
p2 = Point -> Point -> Double -> Point
interpolatePoints Point
p1 Point
p2 Double
0.5

-- | Returns the point between a and b, f units away from a.
interpolatePoints :: Point -> Point -> Double -> Point
interpolatePoints :: Point -> Point -> Double -> Point
interpolatePoints (Point Double
x1 Double
y1) (Point Double
x2 Double
y2) Double
f = Point
newPoint where
  newPoint :: Point
newPoint = Double -> Double -> Point
Point (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
f) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x2) (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
f) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y2)

-- | Negates the coordinates of a point.
negPoint :: Point -> Point
negPoint :: Point -> Point
negPoint (Point Double
x Double
y) = Double -> Double -> Point
Point (-Double
x) (-Double
y)

-- | Checks if a coordinate is inside the horizontal range of a rect.
coordInRectH :: Double -> Rect -> Bool
coordInRectH :: Double -> Rect -> Bool
coordInRectH Double
px (Rect Double
x Double
y Double
w Double
h) = Double
px Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
x Bool -> Bool -> Bool
&& Double
px Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
w

-- | Checks if a coordinate is inside the vertical range of a rect.
coordInRectY :: Double -> Rect -> Bool
coordInRectY :: Double -> Rect -> Bool
coordInRectY Double
py (Rect Double
x Double
y Double
w Double
h) = Double
py Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
y Bool -> Bool -> Bool
&& Double
py Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
h

-- | Adds width and height to a Size.
addToSize :: Size -> Double -> Double -> Maybe Size
addToSize :: Size -> Double -> Double -> Maybe Size
addToSize (Size Double
w Double
h) Double
w2 Double
h2 = Maybe Size
newSize where
  nw :: Double
nw = Double
w Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
w2
  nh :: Double
nh = Double
h Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
h2
  newSize :: Maybe Size
newSize
    | Double
nw Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 Bool -> Bool -> Bool
&& Double
nh Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 = Size -> Maybe Size
forall a. a -> Maybe a
Just (Size -> Maybe Size) -> Size -> Maybe Size
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Size
Size Double
nw Double
nh
    | Bool
otherwise = Maybe Size
forall a. Maybe a
Nothing

-- | Subtracts width and height from a Size.
subtractFromSize :: Size -> Double -> Double -> Maybe Size
subtractFromSize :: Size -> Double -> Double -> Maybe Size
subtractFromSize (Size Double
w Double
h) Double
w2 Double
h2 = Maybe Size
newSize where
  nw :: Double
nw = Double
w Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
w2
  nh :: Double
nh = Double
h Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
h2
  newSize :: Maybe Size
newSize
    | Double
nw Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 Bool -> Bool -> Bool
&& Double
nh Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 = Size -> Maybe Size
forall a. a -> Maybe a
Just (Size -> Maybe Size) -> Size -> Maybe Size
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Size
Size Double
nw Double
nh
    | Bool
otherwise = Maybe Size
forall a. Maybe a
Nothing

-- | Moves a rect by the provided offset.
moveRect :: Point -> Rect -> Rect
moveRect :: Point -> Rect -> Rect
moveRect (Point Double
x Double
y) (Rect Double
rx Double
ry Double
rw Double
rh) = Double -> Double -> Double -> Double -> Rect
Rect (Double
rx Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
x) (Double
ry Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
y) Double
rw Double
rh

-- | Scales a rect by the provided factor.
mulRect :: Double -> Rect -> Rect
mulRect :: Double -> Rect -> Rect
mulRect Double
f (Rect Double
rx Double
ry Double
rw Double
rh) = Double -> Double -> Double -> Double -> Rect
Rect (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rx) (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
ry) (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rw) (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rh)

-- | Returns the middle point of a rect.
rectCenter :: Rect -> Point
rectCenter :: Rect -> Point
rectCenter (Rect Double
rx Double
ry Double
rw Double
rh) = Double -> Double -> Point
Point (Double
rx Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
rw Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2) (Double
ry Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
rh Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2)

-- | Checks if a rectangle is completely inside a rect.
rectInRect :: Rect -> Rect -> Bool
rectInRect :: Rect -> Rect -> Bool
rectInRect Rect
inner Rect
outer = Rect -> Rect -> Bool
rectInRectH Rect
inner Rect
outer Bool -> Bool -> Bool
&& Rect -> Rect -> Bool
rectInRectV Rect
inner Rect
outer

-- | Checks if a rectangle is completely inside a rectangle horizontal area.
rectInRectH :: Rect -> Rect -> Bool
rectInRectH :: Rect -> Rect -> Bool
rectInRectH (Rect Double
x1 Double
y1 Double
w1 Double
h1) (Rect Double
x2 Double
y2 Double
w2 Double
h2) =
  Double
x1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
x2 Bool -> Bool -> Bool
&& Double
x1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
w1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
x2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
w2

-- | Checks if a rectangle is completely inside a rectangle vertical area.
rectInRectV :: Rect -> Rect -> Bool
rectInRectV :: Rect -> Rect -> Bool
rectInRectV (Rect Double
x1 Double
y1 Double
w1 Double
h1) (Rect Double
x2 Double
y2 Double
w2 Double
h2) =
  Double
y1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
y2 Bool -> Bool -> Bool
&& Double
y1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
h1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
y2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
h2

-- | Checks if a rectangle overlaps another rectangle.
rectsOverlap :: Rect -> Rect -> Bool
rectsOverlap :: Rect -> Rect -> Bool
rectsOverlap (Rect Double
x1 Double
y1 Double
w1 Double
h1) (Rect Double
x2 Double
y2 Double
w2 Double
h2) = Bool
overlapX Bool -> Bool -> Bool
&& Bool
overlapY where
  overlapX :: Bool
overlapX = Double
x1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
x2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
w2 Bool -> Bool -> Bool
&& Double
x1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
w1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
x2
  overlapY :: Bool
overlapY = Double
y1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
y2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
h2 Bool -> Bool -> Bool
&& Double
y1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
h1 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
y2

-- | Returns a point bounded to the horizontal and vertical limits of a rect.
rectBoundedPoint :: Rect -> Point -> Point
rectBoundedPoint :: Rect -> Point -> Point
rectBoundedPoint (Rect Double
rx Double
ry Double
rw Double
rh) (Point Double
px Double
py) = Double -> Double -> Point
Point Double
px2 Double
py2 where
  px2 :: Double
px2 = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
rx (Double -> Double) -> (Double -> Double) -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double -> Double
forall a. Ord a => a -> a -> a
min (Double
rx Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
rw) (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
px
  py2 :: Double
py2 = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
ry (Double -> Double) -> (Double -> Double) -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double -> Double
forall a. Ord a => a -> a -> a
min (Double
ry Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
rh) (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
py

-- | Adds individual x, y, w and h coordinates to a rect.
addToRect :: Rect -> Double -> Double -> Double -> Double -> Maybe Rect
addToRect :: Rect -> Double -> Double -> Double -> Double -> Maybe Rect
addToRect (Rect Double
x Double
y Double
w Double
h) Double
l Double
r Double
t Double
b = Maybe Rect
newRect where
  nx :: Double
nx = Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
l
  ny :: Double
ny = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
t
  nw :: Double
nw = Double
w Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
l Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r
  nh :: Double
nh = Double
h Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
b
  newRect :: Maybe Rect
newRect
    | Double
nw Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 Bool -> Bool -> Bool
&& Double
nh Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 = Rect -> Maybe Rect
forall a. a -> Maybe a
Just (Rect -> Maybe Rect) -> Rect -> Maybe Rect
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double -> Double -> Rect
Rect Double
nx Double
ny Double
nw Double
nh
    | Bool
otherwise = Maybe Rect
forall a. Maybe a
Nothing

-- | Subtracts individual x, y, w and h coordinates from a rect.
subtractFromRect :: Rect -> Double -> Double -> Double -> Double -> Maybe Rect
subtractFromRect :: Rect -> Double -> Double -> Double -> Double -> Maybe Rect
subtractFromRect (Rect Double
x Double
y Double
w Double
h) Double
l Double
r Double
t Double
b = Maybe Rect
newRect where
  nx :: Double
nx = Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
l
  ny :: Double
ny = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
t
  nw :: Double
nw = Double
w Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
l Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
r
  nh :: Double
nh = Double
h Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
b
  newRect :: Maybe Rect
newRect
    | Double
nw Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 Bool -> Bool -> Bool
&& Double
nh Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 = Rect -> Maybe Rect
forall a. a -> Maybe a
Just (Rect -> Maybe Rect) -> Rect -> Maybe Rect
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double -> Double -> Rect
Rect Double
nx Double
ny Double
nw Double
nh
    | Bool
otherwise = Maybe Rect
forall a. Maybe a
Nothing

-- | Returns the intersection of two rects, if any.
intersectRects :: Rect -> Rect -> Maybe Rect
intersectRects :: Rect -> Rect -> Maybe Rect
intersectRects (Rect Double
x1 Double
y1 Double
w1 Double
h1) (Rect Double
x2 Double
y2 Double
w2 Double
h2) = Maybe Rect
newRect where
  nx1 :: Double
nx1 = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
x1 Double
x2
  nx2 :: Double
nx2 = Double -> Double -> Double
forall a. Ord a => a -> a -> a
min (Double
x1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
w1) (Double
x2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
w2)
  ny1 :: Double
ny1 = Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
y1 Double
y2
  ny2 :: Double
ny2 = Double -> Double -> Double
forall a. Ord a => a -> a -> a
min (Double
y1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
h1) (Double
y2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
h2)
  nw :: Double
nw = Double
nx2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
nx1
  nh :: Double
nh = Double
ny2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
ny1
  newRect :: Maybe Rect
newRect
    | Double
nw Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 Bool -> Bool -> Bool
&& Double
nh Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
0 = Rect -> Maybe Rect
forall a. a -> Maybe a
Just (Rect -> Maybe Rect) -> Rect -> Maybe Rect
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double -> Double -> Rect
Rect Double
nx1 Double
ny1 Double
nw Double
nh
    | Bool
otherwise = Maybe Rect
forall a. Maybe a
Nothing