    {-# LANGUAGE CPP #-}
    {-|
    A module aimed at making working with GtkBuilder easier.
    It's meant to be used like this (requires OverloadedStrings):

    > buildUI :: BuildFn ()
    > buildUI = do
    >     mainWin <- buildMainWin
    >     buildAboutDialog
    >
    >     widgetShowAll mainWin
    >
    > buildMainWin :: BuildFn ApplicationWindow
    > buildMainWin = do
    >     buildHeaderBar
    >     buildMenuBar
    >     buildMainArea
    >
    >     mainWin <- getObject' ApplicationWindow "mainWin"
    >     on mainWin Destroy mainQuit
    >     return mainWin
    >
    > buildAboutDialog :: BuildFn AboutDialog
    > ...
    >
    > buildHeaderBar :: BuildFn HeaderBar
    > ...
    >
    > buildMenuBar :: BuildFn MenuBar
    > ...
    >
    > buildMainArea :: BuildFn Grid
    > ...
    -}
    module Data.GI.Gtk.BuildFn
        ( BuildFn
        , buildWithBuilder
        , getObject
        ) where

    import           Prelude ()
    import           Prelude.Compat
    import           Control.Monad.Reader (ReaderT, runReaderT, ask, MonadIO, liftIO)
    import           Data.GI.Base (GObject, castTo)
    #if !MIN_VERSION_haskell_gi_base(0,20,1)
    import           Data.GI.Base.BasicTypes (nullToNothing)
    #endif
    import           Data.Maybe (fromJust)
    import qualified Data.Text as T
    import           Foreign.ForeignPtr (ForeignPtr)

    import           GI.Gtk hiding (main)

    type BuildFn a = ReaderT Builder IO a

    buildWithBuilder :: MonadIO m => BuildFn a -> Builder -> m a
    buildWithBuilder :: forall (m :: * -> *) a. MonadIO m => BuildFn a -> Builder -> m a
    buildWithBuilder BuildFn a
    fn Builder
    builder = IO a -> m a
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a -> m a) -> IO a -> m a
    forall a b. (a -> b) -> a -> b
    $ BuildFn a -> Builder -> IO a
    forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
    runReaderT BuildFn a
    fn Builder
    builder

    getObject :: GObject a => (ManagedPtr a -> a) -> T.Text -> BuildFn a
    getObject :: forall a. GObject a => (ManagedPtr a -> a) -> Text -> BuildFn a
    getObject ManagedPtr a -> a
    ctor Text
    name = do
        builder <- ReaderT Builder IO Builder
    forall r (m :: * -> *). MonadReader r m => m r
    ask
    #if MIN_VERSION_haskell_gi_base(0,20,1)
        Just obj <- builderGetObject builder name
    #else
        Just obj <- nullToNothing $ builderGetObject builder name
    #endif
        liftIO $ fromJust <$> castTo ctor obj