{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}

-- | Event handling for declarative widgets.
module GI.Gtk.Declarative.EventSource
  ( EventSource(..)
  , Subscription
  , fromCancellation
  , cancel
  )
where

import           Data.Vector                    ( Vector )

import           GI.Gtk.Declarative.State

-- | Cancel a 'Subscription', meaning that the callback will not be invoked on
-- any subsequent signal emissions.
cancel :: Subscription -> IO ()
cancel :: Subscription -> IO ()
cancel = Vector (IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ (Vector (IO ()) -> IO ())
-> (Subscription -> Vector (IO ())) -> Subscription -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Subscription -> Vector (IO ())
cancellations

-- | An 'EventSource' can be subscribed to, with a callback, returning a
-- 'Subscription'.
class EventSource widget where
  subscribe
    :: widget event     -- ^ Declarative widget with event handlers.
    -> SomeState        -- ^ State of rendered widget tree.
    -> (event -> IO ()) -- ^ Event callback, invoked on each emitted event until
                        -- the 'Subscription' is cancelled, or widget is otherwise
                        -- destroyed.
    -> IO Subscription  -- ^ A 'Subscription' is returned, which can be cancelled.

-- | A 'Subscription' contains zero or more cancellation actions for connected
-- handlers (to a tree of widgets.) When subscribing to a container widget, all
-- child widgets are also subscribed to, and the 'Subscription's are combined
-- using the 'Semigroup' instance.
newtype Subscription = Subscription { Subscription -> Vector (IO ())
cancellations :: Vector (IO ()) }
  deriving (b -> Subscription -> Subscription
NonEmpty Subscription -> Subscription
Subscription -> Subscription -> Subscription
(Subscription -> Subscription -> Subscription)
-> (NonEmpty Subscription -> Subscription)
-> (forall b. Integral b => b -> Subscription -> Subscription)
-> Semigroup Subscription
forall b. Integral b => b -> Subscription -> Subscription
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> Subscription -> Subscription
$cstimes :: forall b. Integral b => b -> Subscription -> Subscription
sconcat :: NonEmpty Subscription -> Subscription
$csconcat :: NonEmpty Subscription -> Subscription
<> :: Subscription -> Subscription -> Subscription
$c<> :: Subscription -> Subscription -> Subscription
Semigroup, Semigroup Subscription
Subscription
Semigroup Subscription =>
Subscription
-> (Subscription -> Subscription -> Subscription)
-> ([Subscription] -> Subscription)
-> Monoid Subscription
[Subscription] -> Subscription
Subscription -> Subscription -> Subscription
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [Subscription] -> Subscription
$cmconcat :: [Subscription] -> Subscription
mappend :: Subscription -> Subscription -> Subscription
$cmappend :: Subscription -> Subscription -> Subscription
mempty :: Subscription
$cmempty :: Subscription
$cp1Monoid :: Semigroup Subscription
Monoid)

-- | Create a subscription from a cancellation IO action.
fromCancellation :: IO () -> Subscription
fromCancellation :: IO () -> Subscription
fromCancellation = Vector (IO ()) -> Subscription
Subscription (Vector (IO ()) -> Subscription)
-> (IO () -> Vector (IO ())) -> IO () -> Subscription
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO () -> Vector (IO ())
forall (f :: * -> *) a. Applicative f => a -> f a
pure