{-# LINE 2 "./Graphics/UI/Gtk/Glade.chs" #-}
-- GIMP Toolkit (GTK) Binding for Haskell: binding to Libglade -*-haskell-*-
-- for loading XML widget specifications
--
-- Author : Manuel M T Chakravarty
-- Created: 13 March 2002
--
-- Copyright (c) 2002 Manuel M T Chakravarty
-- Modified 2003, 2005 by Duncan Coutts (gtk2hs port)
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Library General Public
-- License as published by the Free Software Foundation; either
-- version 2 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Library General Public License for more details.
--
-- Notes:
--
-- glade_xml_signal_autoconnect() is not supported. The C variant is not
-- suitable for Haskell as -rdynamic leads to huge executable and we
-- usually don't want to connect staticly named functions, but closures.
--
-- glade_xml_construct() is not bound, as it doesn't seem to be useful
-- in Haskell. As usual, the signal_connect_data variant for
-- registering signal handlers isn't bound either.  Moreover, the
-- connect_full functions are not bound.
--
-- |
--
-- Libglade facilitates loading of XML specifications of whole widget trees
-- that have been interactively designed with the GUI builder Glade. The
-- present module exports operations for manipulating 'GladeXML' objects.
--
-- * This binding does not support Libglade functionality that is exclusively
-- meant for extending Libglade with new widgets. Like new widgets, such
-- functionality is currently expected to be implemented in C.
--
module Graphics.UI.Gtk.Glade (

  -- * Data types
  --
  GladeXMLClass, GladeXML,

  -- * Creation operations
  --
  xmlNew, xmlNewWithRootAndDomain,

  -- * Obtaining widget handles
  --
  xmlGetWidget, xmlGetWidgetRaw

) where

import Control.Monad (liftM)
import Control.Exception (evaluate)

import System.Glib.FFI
import System.Glib.GType
import Graphics.UI.Gtk.Abstract.Object (makeNewObject)
import System.Glib.GObject (wrapNewGObject)
import Graphics.UI.Gtk.Glade.Types
{-# LINE 66 "./Graphics/UI/Gtk/Glade.chs" #-}
import System.Glib.GList


{-# LINE 69 "./Graphics/UI/Gtk/Glade.chs" #-}


-- | Create a new XML object (and the corresponding widgets) from the given
-- XML file.
--
-- This corresponds to 'xmlNewWithRootAndDomain', but without the ability
-- to specify a root widget or translation domain.
--
xmlNew :: FilePath -> IO (Maybe GladeXML)
xmlNew file =
  withCString file $ \strPtr1 -> do
  xmlPtr <- glade_xml_new strPtr1 nullPtr nullPtr
  if xmlPtr==nullPtr then return Nothing
                     else liftM Just $ wrapNewGObject mkGladeXML (return xmlPtr)

-- | Create a new GladeXML object (and the corresponding widgets) from the
-- given XML file.
--
-- Optionally it will only build the interface from the widget
-- node @root@ (if it is not 'Nothing'). This feature is useful if you only
-- want to build say a toolbar or menu from the XML file, but not the window
-- it is embedded in.
--
-- Note also that the XML parse tree is cached to speed up creating another
-- 'GladeXML' object for the same file.
--
xmlNewWithRootAndDomain ::
    FilePath -- ^ the XML file name.
 -> Maybe String -- ^ @root@ - the widget node in fname to start building
                  -- from (or 'Nothing')
 -> Maybe String -- ^ @domain@ - the translation domain for the XML file (or
                  -- 'Nothing' for default)
 -> IO (Maybe GladeXML)
xmlNewWithRootAndDomain file rootWidgetName domain =
  maybeNull (wrapNewGObject mkGladeXML) $
  withCString file $ \filePtr ->
  maybeWith withCString rootWidgetName $ \rootWidgetNamePtr ->
  maybeWith withCString domain $ \domainPtr ->
  glade_xml_new
{-# LINE 108 "./Graphics/UI/Gtk/Glade.chs" #-}
    filePtr
    rootWidgetNamePtr
    domainPtr

-- | Get the widget that has the given name in
-- the interface description. If the named widget cannot be found
-- or is of the wrong type the result is an error.
--
xmlGetWidget :: (WidgetClass widget) =>
    GladeXML
 -> (GObject -> widget) -- ^ a dynamic cast function that returns the type of
                        -- object that you expect, eg castToButton
 -> String -- ^ the second parameter is the ID of the widget in
                        -- the glade xml file, eg \"button1\".
 -> IO widget
xmlGetWidget xml cast name = do
  maybeWidget <- xmlGetWidgetRaw xml name
  case maybeWidget of
    Just widget -> evaluate (cast (toGObject widget))
     --the cast will return an error if the object is of the wrong type
    Nothing -> fail $ "glade.xmlGetWidget: no object named " ++ show name ++ " in the glade file"

-- | Like 'xmlGetWidget' but it does not do any casting and if the named
-- widget is not found then the result is 'Nothing' rather than an error.
--
xmlGetWidgetRaw :: GladeXML -> String -> IO (Maybe Widget)
xmlGetWidgetRaw xml name =
  maybeNull (makeNewObject mkWidget) $
  withCString name $ \namePtr -> do
  (\(GladeXML arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->glade_xml_get_widget argPtr1 arg2) xml namePtr

foreign import ccall unsafe "glade_xml_new"
  glade_xml_new :: ((Ptr CChar) -> ((Ptr CChar) -> ((Ptr CChar) -> (IO (Ptr GladeXML)))))

foreign import ccall unsafe "glade_xml_get_widget"
  glade_xml_get_widget :: ((Ptr GladeXML) -> ((Ptr CChar) -> (IO (Ptr Widget))))