-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.

{-# LANGUAGE ConstraintKinds, GADTs, FlexibleContexts, MultiParamTypeClasses #-}

{-|
Description : Obtain reactive inputs from GLib signals
Copyright   : Sven Bartscher 2020
License     : MPL-2.0
Maintainer  : sven.bartscher@weltraumschlangen.de
Stability   : experimental

This module provides helpers for constructing input 'Event's,
'Behavior's, and 'Dynamic's from GLib signals and attributes.
-}
module Reflex.GI.Gtk.Input
  ( -- * Obtaining input from GI signals
    -- ** as 'Event's
    MonadGtkSource(eventFromSignalWith)
  , eventOnSignal
  , eventOnSignal0
  , eventFromSignalWith0
  , eventOnSignal1
  , eventFromSignalWith1
  , eventOnSignal0R
  , eventFromSignalWith0R
  , eventOnSignal1R
  , eventFromSignalWith1R
    -- ** as 'Behavior's
  , behaviorOnSignal
  , behaviorFromSignalWith
  , behaviorOnSignal1
  , behaviorFromSignalWith1
  , behaviorOnSignal1R
  , behaviorFromSignalWith1R
    -- ** as 'Dynamic's
  , dynamicOnSignal
  , dynamicFromSignalWith
  , dynamicOnSignal1
  , dynamicFromSignalWith1
  , dynamicOnSignal1R
  , dynamicFromSignalWith1R
    -- * Obtaining input from GI attributes
  , eventOnAttribute
  , eventFromAttributeWith
  , behaviorOnAttribute
  , behaviorFromAttributeWith
  , dynamicOnAttribute
  , dynamicFromAttributeWith
    -- * Synchronous vs asynchronous event triggers
    --
    -- $syncvsasync
  , FireAsync(..)
    -- * Miscellanous
  , Registerer
  ) where

import Data.GI.Base (GObject)
import Data.GI.Base.Attributes ( AttrGetC
                               , AttrLabel
                               , AttrLabelProxy
                               , get
                               )
import Data.GI.Base.Signals ( GObjectNotifySignalInfo
                            , HaskellCallbackType
                            , SignalHandlerId
                            , SignalInfo
                            , SignalProxy(PropertyNotify)
                            , on
                            )
import GHC.TypeLits (KnownSymbol)
import Reflex ( Behavior
              , Dynamic
              , Event
              , MonadHold
              , TriggerEvent
              , hold
              , holdDyn
              )
import Reflex.GI.Gtk.Run.Class ( MonadRunGtk
                               , runGtk
                               )

-- | This class provides the creation of reactive inputs from GLib
-- signals.
class ( MonadRunGtk m
      , TriggerEvent t m
      ) => MonadGtkSource t m where
  -- | Turns a GLib signal into a reactive 'Event'.
  eventFromSignalWith :: ( GObject object
                         , SignalInfo info
                         )
                      => Registerer object info -- ^ A function to
                         -- register a handler for a GLib
                         -- signal. Usually 'on' or 'GI.Gtk.after'.
                      -> FireAsync -- ^ Whether to fire the event
                         -- synchronously or asynchronously. See
                         -- /Synchronous vs asynchronous event triggers/
                         -- for a more in-depth explanation.
                      -> object -- ^ The object emitting the signal
                      -> SignalProxy object info -- ^ The signal to bind to
                      -> ((a -> IO ()) -> HaskellCallbackType info)
                         -- ^ A helper function that is called in the
                         -- handler of the signal. It receives an
                         -- operation @fire@ that emits the
                         -- constructed event with the passed
                         -- value. Is also responsible for handling
                         -- the arguments provided by the signal and
                         -- returning an appropriate value expected by
                         -- the signal.
                      -> m (Event t a) -- ^ An 'Event' that is emitted
                         -- whenever the GLib signal occurs — or
                         -- rather whenever the passed helper function
                         -- calls @fire@.

-- | A shorthand for the types of 'on' and 'GI.Gtk.after' as required
-- by the helpers in this module.
type Registerer object info =
  object -> SignalProxy object info -> HaskellCallbackType info -> IO SignalHandlerId

-- $syncvsasync
--
-- When a signal is emitted by GTK the main loop of GTK is not able to
-- run until the handler(s) for the signal have returned. During this
-- time, the GUI becomes unresponsive. This prevents the user from
-- interacting with the GUI and may cause certain operating systems to
-- display a warning to the user if the GUI stays unresponsive for too
-- long.
--
-- This may or may or may not be desirable depending on the signal
-- being handled and the actions taken in response to the signal. So
-- depending on the circumstances it may be appropriate to carry out
-- all actions triggered by a signal synchronously in the signal
-- handler before it returns, while for other actions it may be more
-- appropriate to trigger the effects of the action to be applied
-- asynchronously (in another thread) and return from the signal
-- handler as soon as possible.
--
-- Usually actions that can be carried out quickly and are expected to
-- show an effect immediately by the user should be handled
-- synchronously, because this provides a relatively intuitive
-- indication to the user that work is still being done in the rare
-- case that the action is not as immediate as intended. This
-- indication usually comes in the form of the GUI being marked as
-- unresponsive and for example the pressed button still displaying
-- the pressed animation.
--
-- Actions that trigger long running processes on the other hand
-- should usually be handled asynchronously, so the user is not left
-- with an unresponsive GUI for an extended period of time. However,
-- this is usually also more elaborate to implement, because the user
-- should still have an indicator that there is still progress being
-- made on the requested action.
--
-- The helpers defined in this module can be parametrized to bind
-- either synchronous signal handlers that wait for the event
-- propagation to fully complete or asynchronous handlers that just
-- mark the signal propagation to be handled later and return as soon
-- as possible. The shorthand versions @*OnSignal*@ bind synchronous
-- handlers, while the more general variants @*FromSignalWith*@
-- support both synchronous and asynchronous handlers.

-- | A sum type to select between synchronous and asynchronous event
-- propagation.
data FireAsync = FireAsync -- ^ Specify asynchronous event propagation
               | FireSync -- ^ Specify synchronous event propagation
  deriving (Int -> FireAsync -> ShowS
[FireAsync] -> ShowS
FireAsync -> String
(Int -> FireAsync -> ShowS)
-> (FireAsync -> String)
-> ([FireAsync] -> ShowS)
-> Show FireAsync
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FireAsync] -> ShowS
$cshowList :: [FireAsync] -> ShowS
show :: FireAsync -> String
$cshow :: FireAsync -> String
showsPrec :: Int -> FireAsync -> ShowS
$cshowsPrec :: Int -> FireAsync -> ShowS
Show, ReadPrec [FireAsync]
ReadPrec FireAsync
Int -> ReadS FireAsync
ReadS [FireAsync]
(Int -> ReadS FireAsync)
-> ReadS [FireAsync]
-> ReadPrec FireAsync
-> ReadPrec [FireAsync]
-> Read FireAsync
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [FireAsync]
$creadListPrec :: ReadPrec [FireAsync]
readPrec :: ReadPrec FireAsync
$creadPrec :: ReadPrec FireAsync
readList :: ReadS [FireAsync]
$creadList :: ReadS [FireAsync]
readsPrec :: Int -> ReadS FireAsync
$creadsPrec :: Int -> ReadS FireAsync
Read, FireAsync -> FireAsync -> Bool
(FireAsync -> FireAsync -> Bool)
-> (FireAsync -> FireAsync -> Bool) -> Eq FireAsync
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FireAsync -> FireAsync -> Bool
$c/= :: FireAsync -> FireAsync -> Bool
== :: FireAsync -> FireAsync -> Bool
$c== :: FireAsync -> FireAsync -> Bool
Eq)

-- | 'eventFromSignalWith' pre-applied to 'on' and 'FireSync'
eventOnSignal :: ( MonadGtkSource t m
                 , GObject object
                 , SignalInfo info
                 )
              => object
              -> SignalProxy object info
              -> ((a -> IO ()) -> HaskellCallbackType info)
              -> m (Event t a)
eventOnSignal :: object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
eventOnSignal = Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
eventFromSignalWith Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | A specialization of 'eventFromSignalWith' for signal handlers
-- without arguments or return types.
eventFromSignalWith0 :: ( MonadGtkSource t m
                        , GObject object
                        , SignalInfo info
                        , HaskellCallbackType info ~ IO ()
                        )
                     => Registerer object info
                     -> FireAsync
                     -> object
                     -> SignalProxy object info
                     -> m (Event t ())
eventFromSignalWith0 :: Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t ())
eventFromSignalWith0 register :: Registerer object info
register sync :: FireAsync
sync object :: object
object signal :: SignalProxy object info
signal =
  Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((() -> IO ()) -> HaskellCallbackType info)
-> m (Event t ())
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
eventFromSignalWith Registerer object info
register FireAsync
sync object
object SignalProxy object info
signal ((() -> IO ()) -> () -> IO ()
forall a b. (a -> b) -> a -> b
$ ())

-- | 'eventFromSignalWith0' pre-applied to 'on' and 'FireSync'
eventOnSignal0 :: ( MonadGtkSource t m
                  , HaskellCallbackType info ~ IO ()
                  , GObject object
                  , SignalInfo info
                  )
               => object
               -> SignalProxy object info
               -> m (Event t ())
eventOnSignal0 :: object -> SignalProxy object info -> m (Event t ())
eventOnSignal0 = Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t ())
forall t (m :: * -> *) object info.
(MonadGtkSource t m, GObject object, SignalInfo info,
 HaskellCallbackType info ~ IO ()) =>
Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t ())
eventFromSignalWith0 Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | A specialization of 'eventFromSignalWith' for signal handlers
-- with exactly one argument and no return type. The argument is used
-- as a value for the emitted 'Event'.
eventFromSignalWith1 :: ( MonadGtkSource t m
                        , HaskellCallbackType info ~ (a -> IO ())
                        , GObject object
                        , SignalInfo info
                        )
                     => Registerer object info
                     -> FireAsync
                     -> object
                     -> SignalProxy object info
                     -> m (Event t a)
eventFromSignalWith1 :: Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t a)
eventFromSignalWith1 register :: Registerer object info
register sync :: FireAsync
sync object :: object
object signal :: SignalProxy object info
signal =
  Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
eventFromSignalWith Registerer object info
register FireAsync
sync object
object SignalProxy object info
signal (a -> IO ()) -> HaskellCallbackType info
forall a. a -> a
id

-- | 'eventFromSignalWith1' pre-applied to 'on' and 'FireSync'
eventOnSignal1 :: ( MonadGtkSource t m
                  , HaskellCallbackType info ~ (a -> IO ())
                  , GObject object
                  , SignalInfo info
                  )
               => object
               -> SignalProxy object info
               -> m (Event t a)
eventOnSignal1 :: object -> SignalProxy object info -> m (Event t a)
eventOnSignal1 = Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t a)
forall t (m :: * -> *) info a object.
(MonadGtkSource t m, HaskellCallbackType info ~ (a -> IO ()),
 GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t a)
eventFromSignalWith1 Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | A specialization of 'eventFromSignalWith' for signal handlers
-- with no arguments and an expected return type. The bound signal
-- handler will returns the supplied constant value.
eventFromSignalWith0R :: ( MonadGtkSource t m
                         , HaskellCallbackType info ~ IO b
                         , GObject object
                         , SignalInfo info
                         )
                      => Registerer object info
                      -> FireAsync
                      -> object
                      -> SignalProxy object info
                      -> b
                      -> m (Event t ())
eventFromSignalWith0R :: Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t ())
eventFromSignalWith0R register :: Registerer object info
register sync :: FireAsync
sync obj :: object
obj signal :: SignalProxy object info
signal x :: b
x =
  Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((() -> IO ()) -> HaskellCallbackType info)
-> m (Event t ())
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
eventFromSignalWith Registerer object info
register FireAsync
sync object
obj SignalProxy object info
signal (((() -> IO ()) -> HaskellCallbackType info) -> m (Event t ()))
-> ((() -> IO ()) -> HaskellCallbackType info) -> m (Event t ())
forall a b. (a -> b) -> a -> b
$ \fire :: () -> IO ()
fire -> b
x b -> IO () -> IO b
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ () -> IO ()
fire ()

-- | 'eventFromSignalWith0R' pre-applied to 'on' and 'FireSync'
eventOnSignal0R :: ( MonadGtkSource t m
                   , HaskellCallbackType info ~ IO b
                   , GObject object
                   , SignalInfo info
                   )
                => object
                -> SignalProxy object info
                -> b
                -> m (Event t ())
eventOnSignal0R :: object -> SignalProxy object info -> b -> m (Event t ())
eventOnSignal0R = Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t ())
forall t (m :: * -> *) info b object.
(MonadGtkSource t m, HaskellCallbackType info ~ IO b,
 GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t ())
eventFromSignalWith0R Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | A specialized version of 'eventFromSignalWith' for signal
-- handlers with exactly one argument and an expected return type. The
-- bound signal handler will always return the supplied constant value
-- and the argument will be used as a value for the emitted event.
eventFromSignalWith1R :: ( MonadGtkSource t m
                         , HaskellCallbackType info ~ (a -> IO b)
                         , GObject object
                         , SignalInfo info
                         )
                      => Registerer object info
                      -> FireAsync
                      -> object
                      -> SignalProxy object info
                      -> b
                      -> m (Event t a)
eventFromSignalWith1R :: Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t a)
eventFromSignalWith1R register :: Registerer object info
register sync :: FireAsync
sync obj :: object
obj signal :: SignalProxy object info
signal r :: b
r =
  Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
eventFromSignalWith Registerer object info
register FireAsync
sync object
obj SignalProxy object info
signal (((a -> IO ()) -> HaskellCallbackType info) -> m (Event t a))
-> ((a -> IO ()) -> HaskellCallbackType info) -> m (Event t a)
forall a b. (a -> b) -> a -> b
$ \fire :: a -> IO ()
fire v :: a
v -> b
r b -> IO () -> IO b
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ a -> IO ()
fire a
v

-- | 'eventFromSignalWith1R' pre-applied to 'on' and 'FireSync'
eventOnSignal1R :: ( MonadGtkSource t m
                   , HaskellCallbackType info ~ (a -> IO b)
                   , GObject object
                   , SignalInfo info
                   )
                => object
                -> SignalProxy object info
                -> b
                -> m (Event t a)
eventOnSignal1R :: object -> SignalProxy object info -> b -> m (Event t a)
eventOnSignal1R = Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t a)
forall t (m :: * -> *) info a b object.
(MonadGtkSource t m, HaskellCallbackType info ~ (a -> IO b),
 GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t a)
eventFromSignalWith1R Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | A shorthand to create an input event with 'eventFromSignalWith' and
-- 'hold' the resulting event using the provided initial value.
behaviorFromSignalWith :: ( MonadGtkSource t m
                          , MonadHold t m
                          , GObject object
                          , SignalInfo info
                          )
                       => Registerer object info
                       -> FireAsync
                       -> a -- ^ The initial value
                       -> object
                       -> SignalProxy object info
                       -> ((a -> IO ()) -> HaskellCallbackType info)
                       -> m (Behavior t a)
behaviorFromSignalWith :: Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Behavior t a)
behaviorFromSignalWith register :: Registerer object info
register sync :: FireAsync
sync initial :: a
initial object :: object
object signal :: SignalProxy object info
signal f :: (a -> IO ()) -> HaskellCallbackType info
f =
  Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
eventFromSignalWith Registerer object info
register FireAsync
sync object
object SignalProxy object info
signal (a -> IO ()) -> HaskellCallbackType info
f m (Event t a)
-> (Event t a -> m (Behavior t a)) -> m (Behavior t a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Event t a -> m (Behavior t a)
forall k (t :: k) (m :: * -> *) a.
MonadHold t m =>
a -> Event t a -> m (Behavior t a)
hold a
initial

-- | 'behaviorFromSignalWith' pre-applied to 'on' and 'FireSync'
behaviorOnSignal :: ( MonadGtkSource t m
                    , MonadHold t m
                    , GObject object
                    , SignalInfo info
                    )
                 => a
                 -> object
                 -> SignalProxy object info
                 -> ((a -> IO ()) -> HaskellCallbackType info)
                 -> m (Behavior t a)
behaviorOnSignal :: a
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Behavior t a)
behaviorOnSignal = Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Behavior t a)
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, MonadHold t m, GObject object,
 SignalInfo info) =>
Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Behavior t a)
behaviorFromSignalWith Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | 'behaviorFromSignalWith' but specialized like
-- 'eventFromSignalWith1'
behaviorFromSignalWith1 :: ( MonadGtkSource t m
                           , MonadHold t m
                           , HaskellCallbackType info ~ (a -> IO ())
                           , GObject object
                           , SignalInfo info
                           )
                        => Registerer object info
                        -> FireAsync
                        -> a
                        -> object
                        -> SignalProxy object info
                        -> m (Behavior t a)
behaviorFromSignalWith1 :: Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> m (Behavior t a)
behaviorFromSignalWith1 register :: Registerer object info
register sync :: FireAsync
sync initial :: a
initial object :: object
object signal :: SignalProxy object info
signal =
  Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t a)
forall t (m :: * -> *) info a object.
(MonadGtkSource t m, HaskellCallbackType info ~ (a -> IO ()),
 GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t a)
eventFromSignalWith1 Registerer object info
register FireAsync
sync object
object SignalProxy object info
signal m (Event t a)
-> (Event t a -> m (Behavior t a)) -> m (Behavior t a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Event t a -> m (Behavior t a)
forall k (t :: k) (m :: * -> *) a.
MonadHold t m =>
a -> Event t a -> m (Behavior t a)
hold a
initial

-- | 'behaviorFromSignalWith1' pre-applied to 'on' and 'FireSync'
behaviorOnSignal1 :: ( MonadGtkSource t m
                     , MonadHold t m
                     , HaskellCallbackType info ~ (a -> IO ())
                     , GObject object
                     , SignalInfo info
                     )
                  => a
                  -> object
                  -> SignalProxy object info
                  -> m (Behavior t a)
behaviorOnSignal1 :: a -> object -> SignalProxy object info -> m (Behavior t a)
behaviorOnSignal1 = Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> m (Behavior t a)
forall t (m :: * -> *) info a object.
(MonadGtkSource t m, MonadHold t m,
 HaskellCallbackType info ~ (a -> IO ()), GObject object,
 SignalInfo info) =>
Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> m (Behavior t a)
behaviorFromSignalWith1 Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | 'behaviorFromSignalWith' but specialized like
-- 'eventFromSignalWith1R'
behaviorFromSignalWith1R :: ( MonadGtkSource t m
                            , MonadHold t m
                            , HaskellCallbackType info ~ (a -> IO b)
                            , GObject object
                            , SignalInfo info
                            )
                         => Registerer object info
                         -> FireAsync
                         -> a
                         -> object
                         -> SignalProxy object info
                         -> b
                         -> m (Behavior t a)
behaviorFromSignalWith1R :: Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> b
-> m (Behavior t a)
behaviorFromSignalWith1R register :: Registerer object info
register sync :: FireAsync
sync initial :: a
initial object :: object
object signal :: SignalProxy object info
signal result :: b
result =
  Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t a)
forall t (m :: * -> *) info a b object.
(MonadGtkSource t m, HaskellCallbackType info ~ (a -> IO b),
 GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t a)
eventFromSignalWith1R Registerer object info
register FireAsync
sync object
object SignalProxy object info
signal b
result m (Event t a)
-> (Event t a -> m (Behavior t a)) -> m (Behavior t a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Event t a -> m (Behavior t a)
forall k (t :: k) (m :: * -> *) a.
MonadHold t m =>
a -> Event t a -> m (Behavior t a)
hold a
initial

-- | 'behaviorFromSignalWith1R' pre-applied to 'on' and 'FireSync'
behaviorOnSignal1R :: ( MonadGtkSource t m
                      , MonadHold t m
                      , HaskellCallbackType info ~ (a -> IO b)
                      , GObject object
                      , SignalInfo info
                      )
                   => a
                   -> object
                   -> SignalProxy object info
                   -> b
                   -> m (Behavior t a)
behaviorOnSignal1R :: a -> object -> SignalProxy object info -> b -> m (Behavior t a)
behaviorOnSignal1R = Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> b
-> m (Behavior t a)
forall t (m :: * -> *) info a b object.
(MonadGtkSource t m, MonadHold t m,
 HaskellCallbackType info ~ (a -> IO b), GObject object,
 SignalInfo info) =>
Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> b
-> m (Behavior t a)
behaviorFromSignalWith1R Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | A shorthand to create an input event with 'eventFromSignalWith' and
-- 'holdDyn' the resulting event using the provided initial value.
dynamicFromSignalWith :: ( MonadGtkSource t m
                         , MonadHold t m
                         , GObject object
                         , SignalInfo info
                         )
                      => Registerer object info
                      -> FireAsync
                      -> a
                      -> object
                      -> SignalProxy object info
                      -> ((a -> IO ()) -> HaskellCallbackType info)
                      -> m (Dynamic t a)
dynamicFromSignalWith :: Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Dynamic t a)
dynamicFromSignalWith register :: Registerer object info
register sync :: FireAsync
sync initial :: a
initial object :: object
object signal :: SignalProxy object info
signal f :: (a -> IO ()) -> HaskellCallbackType info
f =
  Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
eventFromSignalWith Registerer object info
register FireAsync
sync object
object SignalProxy object info
signal (a -> IO ()) -> HaskellCallbackType info
f m (Event t a) -> (Event t a -> m (Dynamic t a)) -> m (Dynamic t a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Event t a -> m (Dynamic t a)
forall k (t :: k) (m :: * -> *) a.
MonadHold t m =>
a -> Event t a -> m (Dynamic t a)
holdDyn a
initial

-- | 'dynamicFromSignalWith' pre-applied to 'on' and 'FireSync'
dynamicOnSignal :: ( MonadGtkSource t m
                   , MonadHold t m
                   , GObject object
                   , SignalInfo info
                   )
                => a
                -> object
                -> SignalProxy object info
                -> ((a -> IO ()) -> HaskellCallbackType info)
                -> m (Dynamic t a)
dynamicOnSignal :: a
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Dynamic t a)
dynamicOnSignal = Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Dynamic t a)
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, MonadHold t m, GObject object,
 SignalInfo info) =>
Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Dynamic t a)
dynamicFromSignalWith Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | 'dynamicFromSignalWith' but specialized like
-- 'eventFromSignalWith1'
dynamicFromSignalWith1 :: ( MonadGtkSource t m
                          , MonadHold t m
                          , HaskellCallbackType info ~ (a -> IO ())
                          , GObject object
                          , SignalInfo info
                          )
                       => Registerer object info
                       -> FireAsync
                       -> a
                       -> object
                       -> SignalProxy object info
                       -> m (Dynamic t a)
dynamicFromSignalWith1 :: Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> m (Dynamic t a)
dynamicFromSignalWith1 register :: Registerer object info
register sync :: FireAsync
sync initial :: a
initial object :: object
object signal :: SignalProxy object info
signal =
  Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t a)
forall t (m :: * -> *) info a object.
(MonadGtkSource t m, HaskellCallbackType info ~ (a -> IO ()),
 GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync -> object -> SignalProxy object info -> m (Event t a)
eventFromSignalWith1 Registerer object info
register FireAsync
sync object
object SignalProxy object info
signal m (Event t a) -> (Event t a -> m (Dynamic t a)) -> m (Dynamic t a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Event t a -> m (Dynamic t a)
forall k (t :: k) (m :: * -> *) a.
MonadHold t m =>
a -> Event t a -> m (Dynamic t a)
holdDyn a
initial

-- | 'dynamicFromSignalWith1' pre-applied to 'on' and 'FireSync'
dynamicOnSignal1 :: ( MonadGtkSource t m
                    , MonadHold t m
                    , HaskellCallbackType info ~ (a -> IO ())
                    , GObject object
                    , SignalInfo info
                    )
                 => a
                 -> object
                 -> SignalProxy object info
                 -> m (Dynamic t a)
dynamicOnSignal1 :: a -> object -> SignalProxy object info -> m (Dynamic t a)
dynamicOnSignal1 = Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> m (Dynamic t a)
forall t (m :: * -> *) info a object.
(MonadGtkSource t m, MonadHold t m,
 HaskellCallbackType info ~ (a -> IO ()), GObject object,
 SignalInfo info) =>
Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> m (Dynamic t a)
dynamicFromSignalWith1 Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | 'dynamicFromSignalWith' but specialized like
-- 'eventFromSignalWith1R'
dynamicFromSignalWith1R :: ( MonadGtkSource t m
                           , MonadHold t m
                           , HaskellCallbackType info ~ (a -> IO b)
                           , GObject object
                           , SignalInfo info
                           )
                        => Registerer object info
                        -> FireAsync
                        -> a
                        -> object
                        -> SignalProxy object info
                        -> b
                        -> m (Dynamic t a)
dynamicFromSignalWith1R :: Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> b
-> m (Dynamic t a)
dynamicFromSignalWith1R register :: Registerer object info
register sync :: FireAsync
sync initial :: a
initial object :: object
object signal :: SignalProxy object info
signal result :: b
result =
  Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t a)
forall t (m :: * -> *) info a b object.
(MonadGtkSource t m, HaskellCallbackType info ~ (a -> IO b),
 GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> b
-> m (Event t a)
eventFromSignalWith1R Registerer object info
register FireAsync
sync object
object SignalProxy object info
signal b
result m (Event t a) -> (Event t a -> m (Dynamic t a)) -> m (Dynamic t a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Event t a -> m (Dynamic t a)
forall k (t :: k) (m :: * -> *) a.
MonadHold t m =>
a -> Event t a -> m (Dynamic t a)
holdDyn a
initial

-- | 'dynamicFromSignalWith1R' pre-applied to 'on' and 'FireSync'
dynamicOnSignal1R :: ( MonadGtkSource t m
                     , MonadHold t m
                     , HaskellCallbackType info ~ (a -> IO b)
                     , GObject object
                     , SignalInfo info
                     )
                  => a
                  -> object
                  -> SignalProxy object info
                  -> b
                  -> m (Dynamic t a)
dynamicOnSignal1R :: a -> object -> SignalProxy object info -> b -> m (Dynamic t a)
dynamicOnSignal1R = Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> b
-> m (Dynamic t a)
forall t (m :: * -> *) info a b object.
(MonadGtkSource t m, MonadHold t m,
 HaskellCallbackType info ~ (a -> IO b), GObject object,
 SignalInfo info) =>
Registerer object info
-> FireAsync
-> a
-> object
-> SignalProxy object info
-> b
-> m (Dynamic t a)
dynamicFromSignalWith1R Registerer object info
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | Construct an input 'Event' that fires whenever a given attribute
-- changes.
eventFromAttributeWith :: ( MonadGtkSource t m
                          , AttrGetC info object attr value
                          , GObject object
                          , KnownSymbol (AttrLabel info)
                          )
                       => Registerer object GObjectNotifySignalInfo
                          -- ^ The function used to register the
                          -- signal handler, usually either 'on' or
                          -- 'GI.Gtk.after'.
                       -> FireAsync -- ^ synchronous or asynchronous
                          -- signal emission
                       -> object -- ^ The object the attribute belongs
                          -- to
                       -> AttrLabelProxy attr -- ^ The attribute to
                          -- watch
                       -> m (Event t value) -- ^ The signal that emits
                          -- new values of the attribute
eventFromAttributeWith :: Registerer object GObjectNotifySignalInfo
-> FireAsync -> object -> AttrLabelProxy attr -> m (Event t value)
eventFromAttributeWith register :: Registerer object GObjectNotifySignalInfo
register sync :: FireAsync
sync object :: object
object attr :: AttrLabelProxy attr
attr =
  Registerer object GObjectNotifySignalInfo
-> FireAsync
-> object
-> SignalProxy object GObjectNotifySignalInfo
-> ((value -> IO ())
    -> HaskellCallbackType GObjectNotifySignalInfo)
-> m (Event t value)
forall t (m :: * -> *) object info a.
(MonadGtkSource t m, GObject object, SignalInfo info) =>
Registerer object info
-> FireAsync
-> object
-> SignalProxy object info
-> ((a -> IO ()) -> HaskellCallbackType info)
-> m (Event t a)
eventFromSignalWith Registerer object GObjectNotifySignalInfo
register FireAsync
sync object
object (AttrLabelProxy attr -> SignalProxy object GObjectNotifySignalInfo
forall info1 (propName :: Symbol) object (pl :: Symbol).
(info1 ~ ResolveAttribute propName object, AttrInfo info1,
 pl ~ AttrLabel info1, KnownSymbol pl) =>
AttrLabelProxy propName
-> SignalProxy object GObjectNotifySignalInfo
PropertyNotify AttrLabelProxy attr
attr) (((value -> IO ()) -> HaskellCallbackType GObjectNotifySignalInfo)
 -> m (Event t value))
-> ((value -> IO ())
    -> HaskellCallbackType GObjectNotifySignalInfo)
-> m (Event t value)
forall a b. (a -> b) -> a -> b
$ \fire :: value -> IO ()
fire _ ->
  object -> AttrLabelProxy attr -> IO value
forall info (attr :: Symbol) obj result (m :: * -> *).
(AttrGetC info obj attr result, MonadIO m) =>
obj -> AttrLabelProxy attr -> m result
get object
object AttrLabelProxy attr
attr IO value -> (value -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= value -> IO ()
fire

-- | 'eventFromAttributeWith' pre-applied to 'on' and 'FireSync'
eventOnAttribute :: ( MonadGtkSource t m
                    , AttrGetC info object attr value
                    , GObject object
                    , KnownSymbol (AttrLabel info)
                    )
                 => object
                 -> AttrLabelProxy attr
                 -> m (Event t value)
eventOnAttribute :: object -> AttrLabelProxy attr -> m (Event t value)
eventOnAttribute = Registerer object GObjectNotifySignalInfo
-> FireAsync -> object -> AttrLabelProxy attr -> m (Event t value)
forall t (m :: * -> *) info object (attr :: Symbol) value.
(MonadGtkSource t m, AttrGetC info object attr value,
 GObject object, KnownSymbol (AttrLabel info)) =>
Registerer object GObjectNotifySignalInfo
-> FireAsync -> object -> AttrLabelProxy attr -> m (Event t value)
eventFromAttributeWith Registerer object GObjectNotifySignalInfo
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | A shorthand to construct an input 'Event' using
-- 'eventFromAttributeWith' and 'hold' it with the current value of
-- the attribute as the initial value.
--
-- This means that the constructed 'Behavior' always has the same
-- value as the attribute.
behaviorFromAttributeWith :: ( MonadGtkSource t m
                             , MonadHold t m
                             , AttrGetC info object attr value
                             , GObject object
                             , KnownSymbol (AttrLabel info)
                             )
                          => Registerer object GObjectNotifySignalInfo
                          -> FireAsync
                          -> object
                          -> AttrLabelProxy attr
                          -> m (Behavior t value)
behaviorFromAttributeWith :: Registerer object GObjectNotifySignalInfo
-> FireAsync
-> object
-> AttrLabelProxy attr
-> m (Behavior t value)
behaviorFromAttributeWith register :: Registerer object GObjectNotifySignalInfo
register sync :: FireAsync
sync object :: object
object attr :: AttrLabelProxy attr
attr = do
  value
initial <- IO value -> m value
forall (m :: * -> *) a. MonadRunGtk m => IO a -> m a
runGtk (IO value -> m value) -> IO value -> m value
forall a b. (a -> b) -> a -> b
$ object -> AttrLabelProxy attr -> IO value
forall info (attr :: Symbol) obj result (m :: * -> *).
(AttrGetC info obj attr result, MonadIO m) =>
obj -> AttrLabelProxy attr -> m result
get object
object AttrLabelProxy attr
attr
  Registerer object GObjectNotifySignalInfo
-> FireAsync -> object -> AttrLabelProxy attr -> m (Event t value)
forall t (m :: * -> *) info object (attr :: Symbol) value.
(MonadGtkSource t m, AttrGetC info object attr value,
 GObject object, KnownSymbol (AttrLabel info)) =>
Registerer object GObjectNotifySignalInfo
-> FireAsync -> object -> AttrLabelProxy attr -> m (Event t value)
eventFromAttributeWith Registerer object GObjectNotifySignalInfo
register FireAsync
sync object
object AttrLabelProxy attr
attr m (Event t value)
-> (Event t value -> m (Behavior t value)) -> m (Behavior t value)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= value -> Event t value -> m (Behavior t value)
forall k (t :: k) (m :: * -> *) a.
MonadHold t m =>
a -> Event t a -> m (Behavior t a)
hold value
initial

-- | 'behaviorFromAttributeWith' pre-applied to 'on' and 'FireSync'
behaviorOnAttribute :: ( MonadGtkSource t m
                       , MonadHold t m
                       , AttrGetC info object attr value
                       , GObject object
                       , KnownSymbol (AttrLabel info)
                       )
                    => object
                    -> AttrLabelProxy attr
                    -> m (Behavior t value)
behaviorOnAttribute :: object -> AttrLabelProxy attr -> m (Behavior t value)
behaviorOnAttribute = Registerer object GObjectNotifySignalInfo
-> FireAsync
-> object
-> AttrLabelProxy attr
-> m (Behavior t value)
forall t (m :: * -> *) info object (attr :: Symbol) value.
(MonadGtkSource t m, MonadHold t m,
 AttrGetC info object attr value, GObject object,
 KnownSymbol (AttrLabel info)) =>
Registerer object GObjectNotifySignalInfo
-> FireAsync
-> object
-> AttrLabelProxy attr
-> m (Behavior t value)
behaviorFromAttributeWith Registerer object GObjectNotifySignalInfo
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync

-- | Like 'behaviorFromAttributeWith' but constructs a 'Dynamic'
-- instead of a 'Behavior'
dynamicFromAttributeWith :: ( MonadGtkSource t m
                            , MonadHold t m
                            , AttrGetC info object attr value
                            , GObject object
                            , KnownSymbol (AttrLabel info)
                            )
                         => Registerer object GObjectNotifySignalInfo
                         -> FireAsync
                         -> object
                         -> AttrLabelProxy attr
                         -> m (Dynamic t value)
dynamicFromAttributeWith :: Registerer object GObjectNotifySignalInfo
-> FireAsync
-> object
-> AttrLabelProxy attr
-> m (Dynamic t value)
dynamicFromAttributeWith register :: Registerer object GObjectNotifySignalInfo
register sync :: FireAsync
sync object :: object
object attr :: AttrLabelProxy attr
attr = do
  value
initial <- IO value -> m value
forall (m :: * -> *) a. MonadRunGtk m => IO a -> m a
runGtk (IO value -> m value) -> IO value -> m value
forall a b. (a -> b) -> a -> b
$ object -> AttrLabelProxy attr -> IO value
forall info (attr :: Symbol) obj result (m :: * -> *).
(AttrGetC info obj attr result, MonadIO m) =>
obj -> AttrLabelProxy attr -> m result
get object
object AttrLabelProxy attr
attr
  Registerer object GObjectNotifySignalInfo
-> FireAsync -> object -> AttrLabelProxy attr -> m (Event t value)
forall t (m :: * -> *) info object (attr :: Symbol) value.
(MonadGtkSource t m, AttrGetC info object attr value,
 GObject object, KnownSymbol (AttrLabel info)) =>
Registerer object GObjectNotifySignalInfo
-> FireAsync -> object -> AttrLabelProxy attr -> m (Event t value)
eventFromAttributeWith Registerer object GObjectNotifySignalInfo
register FireAsync
sync object
object AttrLabelProxy attr
attr m (Event t value)
-> (Event t value -> m (Dynamic t value)) -> m (Dynamic t value)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= value -> Event t value -> m (Dynamic t value)
forall k (t :: k) (m :: * -> *) a.
MonadHold t m =>
a -> Event t a -> m (Dynamic t a)
holdDyn value
initial

-- | 'dynamicFromAttributeWith' pre-applied to 'on' and 'FireSync'
dynamicOnAttribute :: ( MonadGtkSource t m
                      , MonadHold t m
                      , AttrGetC info object attr value
                      , GObject object
                      , KnownSymbol (AttrLabel info)
                      )
                   => object
                   -> AttrLabelProxy attr
                   -> m (Dynamic t value)
dynamicOnAttribute :: object -> AttrLabelProxy attr -> m (Dynamic t value)
dynamicOnAttribute = Registerer object GObjectNotifySignalInfo
-> FireAsync
-> object
-> AttrLabelProxy attr
-> m (Dynamic t value)
forall t (m :: * -> *) info object (attr :: Symbol) value.
(MonadGtkSource t m, MonadHold t m,
 AttrGetC info object attr value, GObject object,
 KnownSymbol (AttrLabel info)) =>
Registerer object GObjectNotifySignalInfo
-> FireAsync
-> object
-> AttrLabelProxy attr
-> m (Dynamic t value)
dynamicFromAttributeWith Registerer object GObjectNotifySignalInfo
forall object info (m :: * -> *).
(GObject object, MonadIO m, SignalInfo info) =>
object
-> SignalProxy object info
-> HaskellCallbackType info
-> m SignalHandlerId
on FireAsync
FireSync