macos-corelibs-0.0.1.0: src/MacSdk/Framework/CoreGraphics/Rect.hsc
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE RankNTypes #-}
#include <Carbon/Carbon.h>
{- | Storable rectangles. -}
module MacSdk.Framework.CoreGraphics.Rect where
import Foreign hiding (with)
import Foreign.C.Types (CBool(..))
import MacSdk.Framework.CoreFoundation
import MacSdk.Framework.Accessibility.Value
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.Managed
type Lens' s a = forall f . Functor f => (a -> f a) -> s -> f s
lens :: (s -> a) -> (s -> a -> s) -> Lens' s a
lens getter setter f s = setter s <$> f (getter s)
data Point = Point { xCoord :: !Double, yCoord :: !Double } deriving (Eq, Show)
data Size = Size { width :: !Double, height :: !Double } deriving (Eq, Show)
-- | Lens focused on the origin of a rectangle.
originL :: Lens' Rect Point
originL = lens origin $ \r p -> case r of Rect _ s -> Rect p s
-- | Lens focused on the size of a rectangle.
sizeL :: Lens' Rect Size
sizeL = lens size $ \r s -> case r of Rect o _ -> Rect o s
-- | Lens focused on the @x@ coordinate of a rectangle.
xL :: Lens' Point Double
xL = lens xCoord $ \p x -> case p of Point _ y -> Point x y
-- | Lens focused on the @y@ coordinate of a rectangle.
yL :: Lens' Point Double
yL = lens yCoord $ \p y -> case p of Point x _ -> Point x y
-- | Lens focused on the width of a rectangle.
widthL :: Lens' Size Double
widthL = lens width $ \s w -> case s of Size _ h -> Size w h
-- | Lens focused on the height of a rectangle.
heightL :: Lens' Size Double
heightL = lens height $ \s h -> case s of Size w _ -> Size w h
-- | Type of rectangular shapes.
data Rect = Rect
{ origin :: Point
-- ^ Origin of the rectangle, corresponding to the top-left corner.
, size :: Size
-- ^ Size of the rectangle.
} deriving (Eq, Show)
instance Storable Point where
sizeOf _ = #{size CGPoint}
alignment _ = #{alignment CGPoint}
peek ptr = do
x' <- #{peek CGPoint, x} ptr
y' <- #{peek CGPoint, y} ptr
return $ Point x' y'
poke ptr (Point x' y') = do
#{poke CGPoint, x} ptr x'
#{poke CGPoint, y} ptr y'
instance Storable Size where
sizeOf _ = #{size CGSize}
alignment _ = #{alignment CGSize}
peek ptr = do
width' <- #{peek CGSize, width} ptr
height' <- #{peek CGSize, height} ptr
return $ Size width' height'
poke ptr (Size width' height') = do
#{poke CGSize, width} ptr width'
#{poke CGSize, height} ptr height'
instance Storable Rect where
sizeOf _ = #{size CGRect}
alignment _ = #{alignment CGRect}
peek ptr = do
origin' <- #{peek CGRect, origin} ptr
size' <- #{peek CGRect, size} ptr
return $ Rect origin' size'
poke ptr (Rect origin' size') = do
#{poke CGRect, origin} ptr origin'
#{poke CGRect, size} ptr size'
foreign import ccall unsafe create_cfpoint :: Ptr Point -> IO CFTypeRef
foreign import ccall unsafe create_cfsize :: Ptr Size -> IO CFTypeRef
foreign import ccall unsafe
ax_value_get_cgpoint :: AXValueRef -> Ptr Point -> IO CBool
foreign import ccall unsafe
ax_value_get_cgsize :: AXValueRef -> Ptr Size -> IO CBool
axValueGetPoint :: AXValueRef -> IO (Maybe Point)
axValueGetPoint ref = alloca $ \p -> do
res <- ax_value_get_cgpoint ref p
if Foreign.toBool res then Just <$> peek p else pure Nothing
valueGetPoint :: Value -> IO (Maybe Point)
valueGetPoint = flip withCFPtr axValueGetPoint
axValueGetSize :: AXValueRef -> IO (Maybe Size)
axValueGetSize ref = alloca $ \p -> do
res <- ax_value_get_cgsize ref p
if Foreign.toBool res then Just <$> peek p else pure Nothing
valueGetSize :: Value -> IO (Maybe Size)
valueGetSize = flip withCFPtr axValueGetSize
-- | Turn a point value into a Core Foundation object.
createCFPoint :: Point -> IO CFObject
createCFPoint pt = alloca $ \p ->
poke p pt >> create_cfpoint p >>= manageCFObj
-- | Turn a size value into a Core Foundation object.
createCFSize :: Size -> IO CFObject
createCFSize sz = alloca $ \p ->
poke p sz >> create_cfsize p >>= manageCFObj
foreign import ccall unsafe "CGRectMakeWithDictionaryRepresentation"
cgRectMakeWithDictionaryRepresentation
:: CFDictionaryRef -> Ptr Rect -> IO CBool
rectMakeWithDictionaryRepresentation :: MonadIO m => Dictionary -> m (Maybe Rect)
rectMakeWithDictionaryRepresentation dict = liftIO . flip with pure $ do
d <- managed $ withCFPtr dict
ptr <- managed alloca
liftIO $ cgRectMakeWithDictionaryRepresentation d ptr >>= \b ->
if toBool b then Just <$> peek ptr else pure Nothing