{-
 *  Programmer:	Piotr Borek
 *  E-mail:     piotrborek@op.pl
 *  Copyright 2017 Piotr Borek
 *
 *  Distributed under the terms of the GPL (GNU Public License)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-}

module Simple.UI.Core.ListenerList (
    ListenerID,
    ListenerList,
    on,
    on_,
    fire,
    listenerNew,
) where

import           Control.Monad
import           Control.Monad.IO.Class
import           Data.IORef

import           Simple.UI.Core.Internal.UIApp

type ListenerID = Integer
type ListenerList a = IORef [(ListenerID, a)]

class Fire a b where
    fire :: w -> (w -> ListenerList a) -> b -> UIApp u ()

instance Fire (UIApp' ()) () where
    fire :: w -> (w -> ListenerList (UIApp' ())) -> () -> UIApp u ()
fire = w -> (w -> ListenerList (UIApp' ())) -> () -> UIApp u ()
forall w u.
w -> (w -> ListenerList (UIApp' ())) -> () -> UIApp u ()
fire0

instance Fire (a -> UIApp' ()) a where
    fire :: w -> (w -> ListenerList (a -> UIApp' ())) -> a -> UIApp u ()
fire = w -> (w -> ListenerList (a -> UIApp' ())) -> a -> UIApp u ()
forall w a u.
w -> (w -> ListenerList (a -> UIApp' ())) -> a -> UIApp u ()
fire1

instance Fire (a -> b -> UIApp' ()) (a, b) where
    fire :: w
-> (w -> ListenerList (a -> b -> UIApp' ()))
-> (a, b)
-> UIApp u ()
fire = w
-> (w -> ListenerList (a -> b -> UIApp' ()))
-> (a, b)
-> UIApp u ()
forall w a b u.
w
-> (w -> ListenerList (a -> b -> UIApp' ()))
-> (a, b)
-> UIApp u ()
fire2

instance Fire (a -> b -> c -> UIApp' ()) (a, b, c) where
    fire :: w
-> (w -> ListenerList (a -> b -> c -> UIApp' ()))
-> (a, b, c)
-> UIApp u ()
fire = w
-> (w -> ListenerList (a -> b -> c -> UIApp' ()))
-> (a, b, c)
-> UIApp u ()
forall w a b c u.
w
-> (w -> ListenerList (a -> b -> c -> UIApp' ()))
-> (a, b, c)
-> UIApp u ()
fire3

instance Fire (a -> b -> c -> d -> UIApp' ()) (a, b, c, d) where
    fire :: w
-> (w -> ListenerList (a -> b -> c -> d -> UIApp' ()))
-> (a, b, c, d)
-> UIApp u ()
fire = w
-> (w -> ListenerList (a -> b -> c -> d -> UIApp' ()))
-> (a, b, c, d)
-> UIApp u ()
forall w a b c d u.
w
-> (w -> ListenerList (a -> b -> c -> d -> UIApp' ()))
-> (a, b, c, d)
-> UIApp u ()
fire4

on :: w -> (w -> ListenerList a) -> a -> UIApp u ListenerID
on :: w -> (w -> ListenerList a) -> a -> UIApp u ListenerID
on w
widget w -> ListenerList a
listeners = ListenerList a -> a -> UIApp u ListenerID
forall a u. ListenerList a -> a -> UIApp u ListenerID
listenerAdd (w -> ListenerList a
listeners w
widget)

on_ :: w -> (w -> ListenerList a) -> a -> UIApp u ()
on_ :: w -> (w -> ListenerList a) -> a -> UIApp u ()
on_ w
widget w -> ListenerList a
listeners a
f = ReaderT (AppConfig u) (StateT AppState IO) ListenerID -> UIApp u ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReaderT (AppConfig u) (StateT AppState IO) ListenerID
 -> UIApp u ())
-> ReaderT (AppConfig u) (StateT AppState IO) ListenerID
-> UIApp u ()
forall a b. (a -> b) -> a -> b
$ w
-> (w -> ListenerList a)
-> a
-> ReaderT (AppConfig u) (StateT AppState IO) ListenerID
forall w a u. w -> (w -> ListenerList a) -> a -> UIApp u ListenerID
on w
widget w -> ListenerList a
listeners a
f

listenerNew :: MonadIO m => m (ListenerList a)
listenerNew :: m (ListenerList a)
listenerNew = IO (ListenerList a) -> m (ListenerList a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (ListenerList a) -> m (ListenerList a))
-> IO (ListenerList a) -> m (ListenerList a)
forall a b. (a -> b) -> a -> b
$ [(ListenerID, a)] -> IO (ListenerList a)
forall a. a -> IO (IORef a)
newIORef []

listenerAdd :: ListenerList a -> a -> UIApp u ListenerID
listenerAdd :: ListenerList a -> a -> UIApp u ListenerID
listenerAdd ListenerList a
listeners a
f = do
    ListenerID
listenerID <- UIApp u ListenerID
forall u. UIApp u ListenerID
uniqueIdNew
    IO () -> ReaderT (AppConfig u) (StateT AppState IO) ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ReaderT (AppConfig u) (StateT AppState IO) ())
-> IO () -> ReaderT (AppConfig u) (StateT AppState IO) ()
forall a b. (a -> b) -> a -> b
$ ListenerList a -> ([(ListenerID, a)] -> [(ListenerID, a)]) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' ListenerList a
listeners (([(ListenerID, a)] -> [(ListenerID, a)]) -> IO ())
-> ([(ListenerID, a)] -> [(ListenerID, a)]) -> IO ()
forall a b. (a -> b) -> a -> b
$ \[(ListenerID, a)]
xs -> (ListenerID
listenerID, a
f)(ListenerID, a) -> [(ListenerID, a)] -> [(ListenerID, a)]
forall a. a -> [a] -> [a]
:[(ListenerID, a)]
xs
    ListenerID -> UIApp u ListenerID
forall (m :: * -> *) a. Monad m => a -> m a
return ListenerID
listenerID

listenerFire0 :: ListenerList (UIApp' ()) -> () -> UIApp u ()
listenerFire0 :: ListenerList (UIApp' ()) -> () -> UIApp u ()
listenerFire0 ListenerList (UIApp' ())
listeners ()
_ = do
    [(ListenerID, UIApp' ())]
list <- IO [(ListenerID, UIApp' ())]
-> ReaderT
     (AppConfig u) (StateT AppState IO) [(ListenerID, UIApp' ())]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [(ListenerID, UIApp' ())]
 -> ReaderT
      (AppConfig u) (StateT AppState IO) [(ListenerID, UIApp' ())])
-> IO [(ListenerID, UIApp' ())]
-> ReaderT
     (AppConfig u) (StateT AppState IO) [(ListenerID, UIApp' ())]
forall a b. (a -> b) -> a -> b
$ ListenerList (UIApp' ()) -> IO [(ListenerID, UIApp' ())]
forall a. IORef a -> IO a
readIORef ListenerList (UIApp' ())
listeners
    UIApp' () -> UIApp u ()
forall a u. UIApp' a -> UIApp u a
liftUIApp' (UIApp' () -> UIApp u ()) -> UIApp' () -> UIApp u ()
forall a b. (a -> b) -> a -> b
$ [(ListenerID, UIApp' ())]
-> ((ListenerID, UIApp' ()) -> UIApp' ()) -> UIApp' ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(ListenerID, UIApp' ())]
list (ListenerID, UIApp' ()) -> UIApp' ()
forall a b. (a, b) -> b
snd

fire0 :: w -> (w -> ListenerList (UIApp' ())) -> () -> UIApp u ()
fire0 :: w -> (w -> ListenerList (UIApp' ())) -> () -> UIApp u ()
fire0 w
widget w -> ListenerList (UIApp' ())
listeners = ListenerList (UIApp' ()) -> () -> UIApp u ()
forall u. ListenerList (UIApp' ()) -> () -> UIApp u ()
listenerFire0 (w -> ListenerList (UIApp' ())
listeners w
widget)

listenerFire1 :: ListenerList (a -> UIApp' ()) -> a -> UIApp u ()
listenerFire1 :: ListenerList (a -> UIApp' ()) -> a -> UIApp u ()
listenerFire1 ListenerList (a -> UIApp' ())
listeners a
a0 = do
    [(ListenerID, a -> UIApp' ())]
list <- IO [(ListenerID, a -> UIApp' ())]
-> ReaderT
     (AppConfig u) (StateT AppState IO) [(ListenerID, a -> UIApp' ())]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [(ListenerID, a -> UIApp' ())]
 -> ReaderT
      (AppConfig u) (StateT AppState IO) [(ListenerID, a -> UIApp' ())])
-> IO [(ListenerID, a -> UIApp' ())]
-> ReaderT
     (AppConfig u) (StateT AppState IO) [(ListenerID, a -> UIApp' ())]
forall a b. (a -> b) -> a -> b
$ ListenerList (a -> UIApp' ()) -> IO [(ListenerID, a -> UIApp' ())]
forall a. IORef a -> IO a
readIORef ListenerList (a -> UIApp' ())
listeners
    UIApp' () -> UIApp u ()
forall a u. UIApp' a -> UIApp u a
liftUIApp' (UIApp' () -> UIApp u ()) -> UIApp' () -> UIApp u ()
forall a b. (a -> b) -> a -> b
$ [(ListenerID, a -> UIApp' ())]
-> ((ListenerID, a -> UIApp' ()) -> UIApp' ()) -> UIApp' ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(ListenerID, a -> UIApp' ())]
list (((ListenerID, a -> UIApp' ()) -> UIApp' ()) -> UIApp' ())
-> ((ListenerID, a -> UIApp' ()) -> UIApp' ()) -> UIApp' ()
forall a b. (a -> b) -> a -> b
$ \(ListenerID
_, a -> UIApp' ()
f) -> a -> UIApp' ()
f a
a0

fire1 :: w -> (w -> ListenerList (a -> UIApp' ())) -> a -> UIApp u ()
fire1 :: w -> (w -> ListenerList (a -> UIApp' ())) -> a -> UIApp u ()
fire1 w
widget w -> ListenerList (a -> UIApp' ())
listeners = ListenerList (a -> UIApp' ()) -> a -> UIApp u ()
forall a u. ListenerList (a -> UIApp' ()) -> a -> UIApp u ()
listenerFire1 (w -> ListenerList (a -> UIApp' ())
listeners w
widget)

listenerFire2 :: ListenerList (a -> b -> UIApp' ()) -> (a, b) -> UIApp u ()
listenerFire2 :: ListenerList (a -> b -> UIApp' ()) -> (a, b) -> UIApp u ()
listenerFire2 ListenerList (a -> b -> UIApp' ())
listeners (a
a0, b
a1) = do
    [(ListenerID, a -> b -> UIApp' ())]
list <- IO [(ListenerID, a -> b -> UIApp' ())]
-> ReaderT
     (AppConfig u)
     (StateT AppState IO)
     [(ListenerID, a -> b -> UIApp' ())]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [(ListenerID, a -> b -> UIApp' ())]
 -> ReaderT
      (AppConfig u)
      (StateT AppState IO)
      [(ListenerID, a -> b -> UIApp' ())])
-> IO [(ListenerID, a -> b -> UIApp' ())]
-> ReaderT
     (AppConfig u)
     (StateT AppState IO)
     [(ListenerID, a -> b -> UIApp' ())]
forall a b. (a -> b) -> a -> b
$ ListenerList (a -> b -> UIApp' ())
-> IO [(ListenerID, a -> b -> UIApp' ())]
forall a. IORef a -> IO a
readIORef ListenerList (a -> b -> UIApp' ())
listeners
    UIApp' () -> UIApp u ()
forall a u. UIApp' a -> UIApp u a
liftUIApp' (UIApp' () -> UIApp u ()) -> UIApp' () -> UIApp u ()
forall a b. (a -> b) -> a -> b
$ [(ListenerID, a -> b -> UIApp' ())]
-> ((ListenerID, a -> b -> UIApp' ()) -> UIApp' ()) -> UIApp' ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(ListenerID, a -> b -> UIApp' ())]
list (((ListenerID, a -> b -> UIApp' ()) -> UIApp' ()) -> UIApp' ())
-> ((ListenerID, a -> b -> UIApp' ()) -> UIApp' ()) -> UIApp' ()
forall a b. (a -> b) -> a -> b
$ \(ListenerID
_, a -> b -> UIApp' ()
f) -> a -> b -> UIApp' ()
f a
a0 b
a1

fire2 :: w -> (w -> ListenerList (a -> b -> UIApp' ())) -> (a, b) -> UIApp u ()
fire2 :: w
-> (w -> ListenerList (a -> b -> UIApp' ()))
-> (a, b)
-> UIApp u ()
fire2 w
widget w -> ListenerList (a -> b -> UIApp' ())
listeners = ListenerList (a -> b -> UIApp' ()) -> (a, b) -> UIApp u ()
forall a b u.
ListenerList (a -> b -> UIApp' ()) -> (a, b) -> UIApp u ()
listenerFire2 (w -> ListenerList (a -> b -> UIApp' ())
listeners w
widget)

listenerFire3 :: ListenerList (a -> b -> c -> UIApp' ()) -> (a, b, c) -> UIApp u ()
listenerFire3 :: ListenerList (a -> b -> c -> UIApp' ()) -> (a, b, c) -> UIApp u ()
listenerFire3 ListenerList (a -> b -> c -> UIApp' ())
listeners (a
a0, b
a1, c
a2) = do
    [(ListenerID, a -> b -> c -> UIApp' ())]
list <- IO [(ListenerID, a -> b -> c -> UIApp' ())]
-> ReaderT
     (AppConfig u)
     (StateT AppState IO)
     [(ListenerID, a -> b -> c -> UIApp' ())]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [(ListenerID, a -> b -> c -> UIApp' ())]
 -> ReaderT
      (AppConfig u)
      (StateT AppState IO)
      [(ListenerID, a -> b -> c -> UIApp' ())])
-> IO [(ListenerID, a -> b -> c -> UIApp' ())]
-> ReaderT
     (AppConfig u)
     (StateT AppState IO)
     [(ListenerID, a -> b -> c -> UIApp' ())]
forall a b. (a -> b) -> a -> b
$ ListenerList (a -> b -> c -> UIApp' ())
-> IO [(ListenerID, a -> b -> c -> UIApp' ())]
forall a. IORef a -> IO a
readIORef ListenerList (a -> b -> c -> UIApp' ())
listeners
    UIApp' () -> UIApp u ()
forall a u. UIApp' a -> UIApp u a
liftUIApp' (UIApp' () -> UIApp u ()) -> UIApp' () -> UIApp u ()
forall a b. (a -> b) -> a -> b
$ [(ListenerID, a -> b -> c -> UIApp' ())]
-> ((ListenerID, a -> b -> c -> UIApp' ()) -> UIApp' ())
-> UIApp' ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(ListenerID, a -> b -> c -> UIApp' ())]
list (((ListenerID, a -> b -> c -> UIApp' ()) -> UIApp' ())
 -> UIApp' ())
-> ((ListenerID, a -> b -> c -> UIApp' ()) -> UIApp' ())
-> UIApp' ()
forall a b. (a -> b) -> a -> b
$ \(ListenerID
_, a -> b -> c -> UIApp' ()
f) -> a -> b -> c -> UIApp' ()
f a
a0 b
a1 c
a2

fire3 :: w -> (w -> ListenerList (a -> b -> c -> UIApp' ())) -> (a, b, c) -> UIApp u ()
fire3 :: w
-> (w -> ListenerList (a -> b -> c -> UIApp' ()))
-> (a, b, c)
-> UIApp u ()
fire3 w
widget w -> ListenerList (a -> b -> c -> UIApp' ())
listeners = ListenerList (a -> b -> c -> UIApp' ()) -> (a, b, c) -> UIApp u ()
forall a b c u.
ListenerList (a -> b -> c -> UIApp' ()) -> (a, b, c) -> UIApp u ()
listenerFire3 (w -> ListenerList (a -> b -> c -> UIApp' ())
listeners w
widget)

listenerFire4 :: ListenerList (a -> b -> c -> d -> UIApp' ()) -> (a, b, c, d) -> UIApp u ()
listenerFire4 :: ListenerList (a -> b -> c -> d -> UIApp' ())
-> (a, b, c, d) -> UIApp u ()
listenerFire4 ListenerList (a -> b -> c -> d -> UIApp' ())
listeners (a
a0, b
a1, c
a2, d
a3) = do
    [(ListenerID, a -> b -> c -> d -> UIApp' ())]
list <- IO [(ListenerID, a -> b -> c -> d -> UIApp' ())]
-> ReaderT
     (AppConfig u)
     (StateT AppState IO)
     [(ListenerID, a -> b -> c -> d -> UIApp' ())]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [(ListenerID, a -> b -> c -> d -> UIApp' ())]
 -> ReaderT
      (AppConfig u)
      (StateT AppState IO)
      [(ListenerID, a -> b -> c -> d -> UIApp' ())])
-> IO [(ListenerID, a -> b -> c -> d -> UIApp' ())]
-> ReaderT
     (AppConfig u)
     (StateT AppState IO)
     [(ListenerID, a -> b -> c -> d -> UIApp' ())]
forall a b. (a -> b) -> a -> b
$ ListenerList (a -> b -> c -> d -> UIApp' ())
-> IO [(ListenerID, a -> b -> c -> d -> UIApp' ())]
forall a. IORef a -> IO a
readIORef ListenerList (a -> b -> c -> d -> UIApp' ())
listeners
    UIApp' () -> UIApp u ()
forall a u. UIApp' a -> UIApp u a
liftUIApp' (UIApp' () -> UIApp u ()) -> UIApp' () -> UIApp u ()
forall a b. (a -> b) -> a -> b
$ [(ListenerID, a -> b -> c -> d -> UIApp' ())]
-> ((ListenerID, a -> b -> c -> d -> UIApp' ()) -> UIApp' ())
-> UIApp' ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(ListenerID, a -> b -> c -> d -> UIApp' ())]
list (((ListenerID, a -> b -> c -> d -> UIApp' ()) -> UIApp' ())
 -> UIApp' ())
-> ((ListenerID, a -> b -> c -> d -> UIApp' ()) -> UIApp' ())
-> UIApp' ()
forall a b. (a -> b) -> a -> b
$ \(ListenerID
_, a -> b -> c -> d -> UIApp' ()
f) -> a -> b -> c -> d -> UIApp' ()
f a
a0 b
a1 c
a2 d
a3

fire4 :: w -> (w -> ListenerList (a -> b -> c -> d -> UIApp' ())) -> (a, b, c, d) -> UIApp u ()
fire4 :: w
-> (w -> ListenerList (a -> b -> c -> d -> UIApp' ()))
-> (a, b, c, d)
-> UIApp u ()
fire4 w
widget w -> ListenerList (a -> b -> c -> d -> UIApp' ())
listeners = ListenerList (a -> b -> c -> d -> UIApp' ())
-> (a, b, c, d) -> UIApp u ()
forall a b c d u.
ListenerList (a -> b -> c -> d -> UIApp' ())
-> (a, b, c, d) -> UIApp u ()
listenerFire4 (w -> ListenerList (a -> b -> c -> d -> UIApp' ())
listeners w
widget)