packages feed

gi-gio-hs-list-model-0.1.0.0: src/Data/GI/Gio/ListModel/SeqStore.hs

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

module Data.GI.Gio.ListModel.SeqStore
  ( SeqStore (..),
    seqStoreNew,
    seqStoreFromList,
    empty,
    replaceList,
    seqStoreLookup,
    getSeq,
  )
where

import Control.Monad.IO.Class (MonadIO (liftIO))
import Data.GI.Base.BasicTypes
import Data.GI.Base.Overloading (HasParentTypes, ParentTypes)
import Data.GI.Gio.ListModel.CustomStore (CustomStore (..), CustomStoreImpl (..), customStoreGetPrivate, customStoreNew)
import Data.IORef (IORef, newIORef, readIORef, writeIORef)
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import GI.Gio.Interfaces.ListModel (ListModel, listModelItemsChanged)

-- | Imlementation of 'CustomStore' backed by 'IORef (Seq a)'.
newtype SeqStore a = SeqStore (ManagedPtr (CustomStore (IORef (Seq a)) a))

instance TypedObject (SeqStore a) where
  glibType = glibType @ListModel

instance GObject (SeqStore a)

instance HasParentTypes (SeqStore a)

type instance ParentTypes (SeqStore a) = '[ListModel]

-- | Create a new 'SeqStore' from a given 'Seq'.
seqStoreNew :: MonadIO m => Seq a -> m (SeqStore a)
seqStoreNew list = liftIO $ do
  listRef <- newIORef list
  let getLength = fromIntegral . Seq.length <$> readIORef listRef
      getNthItem n = Seq.lookup (fromIntegral n) <$> readIORef listRef
      con (CustomStore ptr) = SeqStore ptr
  customStoreNew listRef CustomStoreImpl {..} con

-- | Create a new 'SeqStore' from a given list.
seqStoreFromList :: MonadIO m => [a] -> m (SeqStore a)
seqStoreFromList = seqStoreNew . Seq.fromList

-- | Create a new empty 'SeqStore'.
empty :: MonadIO m => m (SeqStore a)
empty = seqStoreNew mempty

-- | Replace all elements in a 'SeqStore' with elements from a list. This causes
-- @itemsChanged@ event to be emitted.
replaceList :: MonadIO m => SeqStore a -> [a] -> m ()
replaceList store@(SeqStore customStorePtr) newList = liftIO $ do
  priv <- customStoreGetPrivate (CustomStore customStorePtr)
  oldSeq <- readIORef priv
  let newSeq = Seq.fromList newList
  writeIORef priv newSeq
  listModelItemsChanged store 0 (fromIntegral $ Seq.length oldSeq) (fromIntegral $ Seq.length newSeq)

-- | Get element at a given position, uses 'Seq.lookup'.
seqStoreLookup :: MonadIO m => SeqStore a -> Int -> m (Maybe a)
seqStoreLookup store n = Seq.lookup n <$> getSeq store

-- | Get the 'Seq' out of the 'SeqStore'.
getSeq :: MonadIO m => SeqStore a -> m (Seq a)
getSeq store@(SeqStore customStorePtr) =
  liftIO $ readIORef =<< customStoreGetPrivate (CustomStore customStorePtr)