{-# LANGUAGE TypeApplications #-}


-- | Copyright  : Will Thompson and Iñaki García Etxebarria
-- License    : LGPL-2.1
-- Maintainer : Iñaki García Etxebarria
-- 
-- Creates widgets for the items taken from a @GListModel@.
-- 
-- This is one of the core concepts of handling list widgets such
-- as t'GI.Gtk.Objects.ListView.ListView' or t'GI.Gtk.Objects.GridView.GridView'.
-- 
-- The @GtkListItemFactory@ is tasked with creating widgets for items
-- taken from the model when the views need them and updating them as
-- the items displayed by the view change.
-- 
-- A view is usually only able to display anything after both a factory
-- and a model have been set on the view. So it is important that you do
-- not skip this step when setting up your first view.
-- 
-- Because views do not display the whole list at once but only a few
-- items, they only need to maintain a few widgets at a time. They will
-- instruct the @GtkListItemFactory@ to create these widgets and bind them
-- to the items that are currently displayed.
-- 
-- As the list model changes or the user scrolls to the list, the items will
-- change and the view will instruct the factory to bind the widgets to those
-- new items.
-- 
-- The actual widgets used for displaying those widgets is provided by you.
-- 
-- When the factory needs widgets created, it will create a @GtkListItem@
-- and hand it to your code to set up a widget for. This list item will provide
-- various properties with information about what item to display and provide
-- you with some opportunities to configure its behavior. See the
-- t'GI.Gtk.Objects.ListItem.ListItem' documentation for further details.
-- 
-- Various implementations of @GtkListItemFactory@ exist to allow you different
-- ways to provide those widgets. The most common implementations are
-- t'GI.Gtk.Objects.BuilderListItemFactory.BuilderListItemFactory' which takes a @GtkBuilder@ .ui file
-- and then creates widgets and manages everything automatically from the
-- information in that file and t'GI.Gtk.Objects.SignalListItemFactory.SignalListItemFactory' which allows
-- you to connect to signals with your own code and retain full control over
-- how the widgets are setup and managed.
-- 
-- A @GtkListItemFactory@ is supposed to be final - that means its behavior should
-- not change and the first widget created from it should behave the same way as
-- the last widget created from it.
-- If you intend to do changes to the behavior, it is recommended that you create
-- a new @GtkListItemFactory@ which will allow the views to recreate its widgets.
-- 
-- Once you have chosen your factory and created it, you need to set it on the view
-- widget you want to use it with, such as via 'GI.Gtk.Objects.ListView.listViewSetFactory'.
-- Reusing factories across different views is allowed, but very uncommon.

#if (MIN_VERSION_haskell_gi_overloading(1,0,0) && !defined(__HADDOCK_VERSION__))
#define ENABLE_OVERLOADING
#endif

module GI.Gtk.Objects.ListItemFactory
    ( 

-- * Exported types
    ListItemFactory(..)                     ,
    IsListItemFactory                       ,
    toListItemFactory                       ,


 -- * Methods
-- | 
-- 
--  === __Click to display all available methods, including inherited ones__
-- ==== Methods
-- [bindProperty]("GI.GObject.Objects.Object#g:method:bindProperty"), [bindPropertyFull]("GI.GObject.Objects.Object#g:method:bindPropertyFull"), [forceFloating]("GI.GObject.Objects.Object#g:method:forceFloating"), [freezeNotify]("GI.GObject.Objects.Object#g:method:freezeNotify"), [getv]("GI.GObject.Objects.Object#g:method:getv"), [isFloating]("GI.GObject.Objects.Object#g:method:isFloating"), [notify]("GI.GObject.Objects.Object#g:method:notify"), [notifyByPspec]("GI.GObject.Objects.Object#g:method:notifyByPspec"), [ref]("GI.GObject.Objects.Object#g:method:ref"), [refSink]("GI.GObject.Objects.Object#g:method:refSink"), [runDispose]("GI.GObject.Objects.Object#g:method:runDispose"), [stealData]("GI.GObject.Objects.Object#g:method:stealData"), [stealQdata]("GI.GObject.Objects.Object#g:method:stealQdata"), [thawNotify]("GI.GObject.Objects.Object#g:method:thawNotify"), [unref]("GI.GObject.Objects.Object#g:method:unref"), [watchClosure]("GI.GObject.Objects.Object#g:method:watchClosure").
-- 
-- ==== Getters
-- [getData]("GI.GObject.Objects.Object#g:method:getData"), [getProperty]("GI.GObject.Objects.Object#g:method:getProperty"), [getQdata]("GI.GObject.Objects.Object#g:method:getQdata").
-- 
-- ==== Setters
-- [setData]("GI.GObject.Objects.Object#g:method:setData"), [setDataFull]("GI.GObject.Objects.Object#g:method:setDataFull"), [setProperty]("GI.GObject.Objects.Object#g:method:setProperty").

#if defined(ENABLE_OVERLOADING)
    ResolveListItemFactoryMethod            ,
#endif



    ) where

import Data.GI.Base.ShortPrelude
import qualified Data.GI.Base.ShortPrelude as SP
import qualified Data.GI.Base.Overloading as O
import qualified Prelude as P

import qualified Data.GI.Base.Attributes as GI.Attributes
import qualified Data.GI.Base.BasicTypes as B.Types
import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GArray as B.GArray
import qualified Data.GI.Base.GClosure as B.GClosure
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GHashTable as B.GHT
import qualified Data.GI.Base.GVariant as B.GVariant
import qualified Data.GI.Base.GValue as B.GValue
import qualified Data.GI.Base.GParamSpec as B.GParamSpec
import qualified Data.GI.Base.CallStack as B.CallStack
import qualified Data.GI.Base.Properties as B.Properties
import qualified Data.GI.Base.Signals as B.Signals
import qualified Control.Monad.IO.Class as MIO
import qualified Data.Coerce as Coerce
import qualified Data.Text as T
import qualified Data.Kind as DK
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map
import qualified Foreign.Ptr as FP
import qualified GHC.OverloadedLabels as OL
import qualified GHC.Records as R
import qualified Data.Word as DW
import qualified Data.Int as DI
import qualified System.Posix.Types as SPT
import qualified Foreign.C.Types as FCT

-- Workaround for https://gitlab.haskell.org/ghc/ghc/-/issues/23392
#if MIN_VERSION_base(4,18,0)
import qualified GI.GObject.Objects.Object as GObject.Object

#else
import qualified GI.GObject.Objects.Object as GObject.Object

#endif

-- | Memory-managed wrapper type.
newtype ListItemFactory = ListItemFactory (SP.ManagedPtr ListItemFactory)
    deriving (Eq)

instance SP.ManagedPtrNewtype ListItemFactory where
    toManagedPtr (ListItemFactory p) = p

foreign import ccall "gtk_list_item_factory_get_type"
    c_gtk_list_item_factory_get_type :: IO B.Types.GType

instance B.Types.TypedObject ListItemFactory where
    glibType = c_gtk_list_item_factory_get_type

instance B.Types.GObject ListItemFactory

-- | Type class for types which can be safely cast to t'ListItemFactory', for instance with `toListItemFactory`.
class (SP.GObject o, O.IsDescendantOf ListItemFactory o) => IsListItemFactory o
instance (SP.GObject o, O.IsDescendantOf ListItemFactory o) => IsListItemFactory o

instance O.HasParentTypes ListItemFactory
type instance O.ParentTypes ListItemFactory = '[GObject.Object.Object]

-- | Cast to t'ListItemFactory', for types for which this is known to be safe. For general casts, use 'Data.GI.Base.ManagedPtr.castTo'.
toListItemFactory :: (MIO.MonadIO m, IsListItemFactory o) => o -> m ListItemFactory
toListItemFactory = MIO.liftIO . B.ManagedPtr.unsafeCastTo ListItemFactory

-- | Convert t'ListItemFactory' to and from t'Data.GI.Base.GValue.GValue'. See 'Data.GI.Base.GValue.toGValue' and 'Data.GI.Base.GValue.fromGValue'.
instance B.GValue.IsGValue (Maybe ListItemFactory) where
    gvalueGType_ = c_gtk_list_item_factory_get_type
    gvalueSet_ gv P.Nothing = B.GValue.set_object gv (FP.nullPtr :: FP.Ptr ListItemFactory)
    gvalueSet_ gv (P.Just obj) = B.ManagedPtr.withManagedPtr obj (B.GValue.set_object gv)
    gvalueGet_ gv = do
        ptr <- B.GValue.get_object gv :: IO (FP.Ptr ListItemFactory)
        if ptr /= FP.nullPtr
        then P.Just <$> B.ManagedPtr.newObject ListItemFactory ptr
        else return P.Nothing
        
    

#if defined(ENABLE_OVERLOADING)
type family ResolveListItemFactoryMethod (t :: Symbol) (o :: DK.Type) :: DK.Type where
    ResolveListItemFactoryMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
    ResolveListItemFactoryMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
    ResolveListItemFactoryMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
    ResolveListItemFactoryMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
    ResolveListItemFactoryMethod "getv" o = GObject.Object.ObjectGetvMethodInfo
    ResolveListItemFactoryMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
    ResolveListItemFactoryMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
    ResolveListItemFactoryMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
    ResolveListItemFactoryMethod "ref" o = GObject.Object.ObjectRefMethodInfo
    ResolveListItemFactoryMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
    ResolveListItemFactoryMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
    ResolveListItemFactoryMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
    ResolveListItemFactoryMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
    ResolveListItemFactoryMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
    ResolveListItemFactoryMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo
    ResolveListItemFactoryMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
    ResolveListItemFactoryMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
    ResolveListItemFactoryMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
    ResolveListItemFactoryMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
    ResolveListItemFactoryMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
    ResolveListItemFactoryMethod "setDataFull" o = GObject.Object.ObjectSetDataFullMethodInfo
    ResolveListItemFactoryMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
    ResolveListItemFactoryMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveListItemFactoryMethod t ListItemFactory, O.OverloadedMethod info ListItemFactory p) => OL.IsLabel t (ListItemFactory -> p) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.overloadedMethod @info
#else
    fromLabel _ = O.overloadedMethod @info
#endif

#if MIN_VERSION_base(4,13,0)
instance (info ~ ResolveListItemFactoryMethod t ListItemFactory, O.OverloadedMethod info ListItemFactory p, R.HasField t ListItemFactory p) => R.HasField t ListItemFactory p where
    getField = O.overloadedMethod @info

#endif

instance (info ~ ResolveListItemFactoryMethod t ListItemFactory, O.OverloadedMethodInfo info ListItemFactory) => OL.IsLabel t (O.MethodProxy info ListItemFactory) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.MethodProxy
#else
    fromLabel _ = O.MethodProxy
#endif

#endif

#if defined(ENABLE_OVERLOADING)
instance O.HasAttributeList ListItemFactory
type instance O.AttributeList ListItemFactory = ListItemFactoryAttributeList
type ListItemFactoryAttributeList = ('[ ] :: [(Symbol, DK.Type)])
#endif

#if defined(ENABLE_OVERLOADING)
#endif

#if defined(ENABLE_OVERLOADING)
type instance O.SignalList ListItemFactory = ListItemFactorySignalList
type ListItemFactorySignalList = ('[ '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, DK.Type)])

#endif


