{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

-- | Allows a custom data structure to be used with ListView introduced in GTK4.
-- The model 'Data.GI.Gio.ListModel.SeqStore.SeqStore' is based on
-- 'CustomStore'. This module should only be required for implementing a new
-- type of store.
--
-- The users of a 'CustomStore' will need to handle the 'GI.GObject.Object' that is
-- returned by 'GI.Gtk.ListItem.listItemGetItem', for this
-- "Data.GI.Gio.ListModel.CustomStoreItem" can be used.
module Data.GI.Gio.ListModel.CustomStore
  ( CustomStore (..),
    customStoreNew,
    customStoreGetPrivate,
    CustomStoreImpl (..),
  )
where

import Control.Monad.IO.Class (MonadIO (liftIO))
import Data.GI.Base (newObject, withManagedPtr)
import Data.GI.Base.BasicTypes
import Data.GI.Base.Overloading (HasParentTypes, ParentTypes)
import Data.GI.Gio.ListModel.Internal.ListItemCImports (giGioHsListItemNew, listItemGetType)
import Data.Kind (Type)
import Data.Word (Word16)
import Foreign.C.Types
import Foreign.Ptr
import Foreign.StablePtr
import GI.Gio.Interfaces.ListModel (ListModel)

-- C Imports
foreign import ccall "GiGioHsListStore.h gi_gio_hs_list_store_new"
  giGioHsListStoreNew ::
    StablePtr (CustomStoreImpl model a) ->
    StablePtr private ->
    IO (Ptr (CustomStore private a))

foreign import ccall "giGioHsListStore.hs gi_gio_hs_list_store_get_priv"
  giGioHsListStoreGetPriv :: Ptr (CustomStore private a) -> IO (StablePtr private)

-- | A 'CustomStore' is an instance of 'GListModel'. This can be used for any
-- widget that stores 'GListModel'. The user may either create an instance using
-- 'customStoreNew' or use the predefined model
-- 'Data.GI.Gio.ListModel.SeqStore'.
--
-- The 'private' type can be used to represent any data that might be needed to
-- perform operations on the implmentation of 'CustomStore'. For example, this
-- can be an 'Data.IORef.IORef' which can be manipulated as the list needs
-- manipulating.
newtype CustomStore private a = CustomStore (ManagedPtr (CustomStore private a))

instance HasParentTypes (CustomStore private row)

type instance ParentTypes (CustomStore private row) = '[ListModel]

instance TypedObject (CustomStore private a) where
  glibType :: IO GType
glibType = TypedObject ListModel => IO GType
forall a. TypedObject a => IO GType
glibType @ListModel

instance GObject (CustomStore private a)

-- | Operations required to be defined for any implementation of 'CustomStore'.
data CustomStoreImpl (model :: Type -> Type) a = CustomStoreImpl
  { CustomStoreImpl model a -> IO Word16
getLength :: IO Word16,
    CustomStoreImpl model a -> Word16 -> IO (Maybe a)
getNthItem :: Word16 -> IO (Maybe a)
  }

-- | Create a new instance of a 'CustomStore'.
customStoreNew :: MonadIO m => private -> CustomStoreImpl model a -> (CustomStore private a -> model a) -> m (model a)
customStoreNew :: private
-> CustomStoreImpl model a
-> (CustomStore private a -> model a)
-> m (model a)
customStoreNew private
private CustomStoreImpl model a
impl CustomStore private a -> model a
con = IO (model a) -> m (model a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (model a) -> m (model a)) -> IO (model a) -> m (model a)
forall a b. (a -> b) -> a -> b
$ do
  StablePtr private
privPtr <- private -> IO (StablePtr private)
forall a. a -> IO (StablePtr a)
newStablePtr private
private
  StablePtr (CustomStoreImpl model a)
implPtr <- CustomStoreImpl model a -> IO (StablePtr (CustomStoreImpl model a))
forall a. a -> IO (StablePtr a)
newStablePtr CustomStoreImpl model a
impl
  Ptr (CustomStore private a)
storePtr <- StablePtr (CustomStoreImpl model a)
-> StablePtr private -> IO (Ptr (CustomStore private a))
forall (model :: * -> *) a private.
StablePtr (CustomStoreImpl model a)
-> StablePtr private -> IO (Ptr (CustomStore private a))
giGioHsListStoreNew StablePtr (CustomStoreImpl model a)
implPtr StablePtr private
privPtr
  CustomStore private a -> model a
con (CustomStore private a -> model a)
-> IO (CustomStore private a) -> IO (model a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ManagedPtr (CustomStore private a) -> CustomStore private a)
-> Ptr (CustomStore private a) -> IO (CustomStore private a)
forall a b.
(HasCallStack, GObject a, GObject b) =>
(ManagedPtr a -> a) -> Ptr b -> IO a
newObject ManagedPtr (CustomStore private a) -> CustomStore private a
forall private a.
ManagedPtr (CustomStore private a) -> CustomStore private a
CustomStore Ptr (CustomStore private a)
storePtr

customStoreGetPrivate :: MonadIO m => CustomStore private a -> m private
customStoreGetPrivate :: CustomStore private a -> m private
customStoreGetPrivate CustomStore private a
store =
  IO private -> m private
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO private -> m private) -> IO private -> m private
forall a b. (a -> b) -> a -> b
$ CustomStore private a
-> (Ptr (CustomStore private a) -> IO (StablePtr private))
-> IO (StablePtr private)
forall a c.
(HasCallStack, ManagedPtrNewtype a) =>
a -> (Ptr a -> IO c) -> IO c
withManagedPtr CustomStore private a
store Ptr (CustomStore private a) -> IO (StablePtr private)
forall private a.
Ptr (CustomStore private a) -> IO (StablePtr private)
giGioHsListStoreGetPriv IO (StablePtr private)
-> (StablePtr private -> IO private) -> IO private
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= StablePtr private -> IO private
forall a. StablePtr a -> IO a
deRefStablePtr

-- C Exports

{-# ANN module ("HLint: ignore Use camelCase" :: String) #-}

listModelGetNItems_static :: StablePtr (CustomStoreImpl model a) -> IO CUInt
listModelGetNItems_static :: StablePtr (CustomStoreImpl model a) -> IO CUInt
listModelGetNItems_static StablePtr (CustomStoreImpl model a)
storePtr = do
  CustomStoreImpl model a
impl <- StablePtr (CustomStoreImpl model a) -> IO (CustomStoreImpl model a)
forall a. StablePtr a -> IO a
deRefStablePtr StablePtr (CustomStoreImpl model a)
storePtr
  (Word16 -> CUInt) -> IO Word16 -> IO CUInt
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word16 -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IO Word16 -> IO CUInt)
-> (CustomStoreImpl model a -> IO Word16)
-> CustomStoreImpl model a
-> IO CUInt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CustomStoreImpl model a -> IO Word16
forall (model :: * -> *) a. CustomStoreImpl model a -> IO Word16
getLength (CustomStoreImpl model a -> IO CUInt)
-> CustomStoreImpl model a -> IO CUInt
forall a b. (a -> b) -> a -> b
$ CustomStoreImpl model a
impl

foreign export ccall "gi_gio_hs_list_store_get_n_items_impl"
  listModelGetNItems_static :: StablePtr (CustomStoreImpl model a) -> IO CUInt

listModelGetItem_static :: StablePtr (CustomStoreImpl model a) -> CUInt -> IO (Ptr ())
listModelGetItem_static :: StablePtr (CustomStoreImpl model a) -> CUInt -> IO (Ptr ())
listModelGetItem_static StablePtr (CustomStoreImpl model a)
storePtr CUInt
cpos = do
  CustomStoreImpl model a
impl <- StablePtr (CustomStoreImpl model a) -> IO (CustomStoreImpl model a)
forall a. StablePtr a -> IO a
deRefStablePtr StablePtr (CustomStoreImpl model a)
storePtr
  let pos :: Word16
pos = CUInt -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
cpos
  Maybe a
maybeItem <- CustomStoreImpl model a -> Word16 -> IO (Maybe a)
forall (model :: * -> *) a.
CustomStoreImpl model a -> Word16 -> IO (Maybe a)
getNthItem CustomStoreImpl model a
impl Word16
pos
  case Maybe a
maybeItem of
    Just a
item -> StablePtr a -> IO (Ptr ())
forall a. StablePtr a -> IO (Ptr ())
giGioHsListItemNew (StablePtr a -> IO (Ptr ())) -> IO (StablePtr a) -> IO (Ptr ())
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< a -> IO (StablePtr a)
forall a. a -> IO (StablePtr a)
newStablePtr a
item
    Maybe a
Nothing -> Ptr () -> IO (Ptr ())
forall (f :: * -> *) a. Applicative f => a -> f a
pure Ptr ()
forall a. Ptr a
nullPtr

foreign export ccall "gi_gio_hs_list_store_get_item_impl"
  listModelGetItem_static :: StablePtr (CustomStoreImpl model a) -> CUInt -> IO (Ptr ())

listModelGetItemType_static :: StablePtr (CustomStoreImpl model a) -> IO CGType
listModelGetItemType_static :: StablePtr (CustomStoreImpl model a) -> IO CGType
listModelGetItemType_static StablePtr (CustomStoreImpl model a)
_ = IO CGType
listItemGetType

foreign export ccall "gi_gio_hs_list_store_get_item_type_impl"
  listModelGetItemType_static :: StablePtr (CustomStoreImpl model a) -> IO CGType