{-# LANGUAGE DefaultSignatures      #-}
{-# LANGUAGE DeriveFunctor          #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE TypeFamilies           #-}

-- | Shared interfaces for containers.
module GI.Gtk.Declarative.Container.Class where

import           Data.Int                       ( Int32 )
import           Data.Vector                    ( Vector )
import qualified GI.Gtk                        as Gtk

-- | Describes supported GTK+ containers and their specialized APIs for
-- appending and replacing child widgets.
class IsContainer container child | container -> child where
  -- | Append a child widget to the container.
  appendChild
    :: container    -- ^ Container widget
    -> child event  -- ^ Declarative child widget
    -> Gtk.Widget   -- ^ GTK child widget to append
    -> IO ()
  -- | Replace the child widget at the given index in the container.
  replaceChild
    :: container    -- ^ Container widget
    -> child event  -- ^ Declarative child widget
    -> Int32        -- ^ Index to replace at
    -> Gtk.Widget   -- ^ Old GTK widget to replace
    -> Gtk.Widget   -- ^ New GTK widget to replace with
    -> IO ()

-- | Common collection type for child widgets, used when patching containers.
newtype Children child event = Children { Children child event -> Vector (child event)
unChildren :: Vector (child event) }
  deriving (a -> Children child b -> Children child a
(a -> b) -> Children child a -> Children child b
(forall a b. (a -> b) -> Children child a -> Children child b)
-> (forall a b. a -> Children child b -> Children child a)
-> Functor (Children child)
forall a b. a -> Children child b -> Children child a
forall a b. (a -> b) -> Children child a -> Children child b
forall (child :: * -> *) a b.
Functor child =>
a -> Children child b -> Children child a
forall (child :: * -> *) a b.
Functor child =>
(a -> b) -> Children child a -> Children child b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Children child b -> Children child a
$c<$ :: forall (child :: * -> *) a b.
Functor child =>
a -> Children child b -> Children child a
fmap :: (a -> b) -> Children child a -> Children child b
$cfmap :: forall (child :: * -> *) a b.
Functor child =>
(a -> b) -> Children child a -> Children child b
Functor)

-- | Converts a specific collection type to 'Children'.
class ToChildren widget parent child | widget -> parent, widget -> child where
  toChildren :: (Gtk.ManagedPtr widget -> widget) -> parent (child event) -> Children child event

  default toChildren :: parent ~ Vector => (Gtk.ManagedPtr widget -> widget) -> parent (child event) -> Children child event
  toChildren _ = parent (child event) -> Children child event
forall (child :: * -> *) event.
Vector (child event) -> Children child event
Children