content: {-# OPTIONS_GHC -fno-warn-orphans #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE OverloadedLabels      #-}
  {-# LANGUAGE OverloadedLists       #-}
  {-# LANGUAGE OverloadedStrings     #-}
  {-# LANGUAGE RecordWildCards       #-}
  
  -- | Implementation of 'Gtk.Notebook' as a declarative container.
  module GI.Gtk.Declarative.Container.Notebook
    ( Page
    , page
    , pageWithTab
    , notebook
    )
  where
  
  import           Control.Monad                  ( void )
  import           Data.Maybe                     ( isNothing )
  import           Data.Text                      ( Text
                                                  , pack
                                                  )
  import           Data.Vector                    ( Vector )
  import           GHC.Ptr                        ( nullPtr )
  import qualified GI.GLib                       as GLib
  import qualified GI.Gtk                        as Gtk
  import           GI.Gtk.Declarative.Attributes
  import           GI.Gtk.Declarative.Container
  import           GI.Gtk.Declarative.Container.Class
  import           GI.Gtk.Declarative.SingleWidget
  import           GI.Gtk.Declarative.Widget
  
  -- | Describes a page to be added to a 'Notebook'
  data Page event =
    Page
      { tabLabel :: Widget event
      , child    :: Widget event
      }
  
  -- | Create a page with a textual label and an arbitrary content widget.
  page :: Text -> Widget event -> Page event
  page label = pageWithTab (widget Gtk.Label [#label := label])
  
  -- | Create a page with arbitrary widgets for both label and content.
  pageWithTab :: Widget event -> Widget event -> Page event
  pageWithTab = Page
  
  -- | Create a 'Notebook' by combining multiple pages.
  notebook
    :: Vector (Attribute Gtk.Notebook event)
    -> Vector (Page event)
    -> Widget event
  notebook attrs children =
    let childrenAndTabs = children >>= (\Page {..} -> [child, tabLabel])
    in  container Gtk.Notebook attrs childrenAndTabs
  
  instance ToChildren Gtk.Notebook Vector Widget
  
  instance IsContainer Gtk.Notebook Widget where
    appendChild parent _ new = do
      lastPage <- Gtk.notebookGetNthPage parent (-1)
      case lastPage of
        -- this is the first page to be added
        Nothing -> do
          void $ Gtk.notebookAppendPage parent new (Nothing :: Maybe Gtk.Widget)
        Just p -> do
          label <- Gtk.notebookGetTabLabel parent p
          if isNothing label
              -- this page must already have a child, we just need to set the label
            then do
              Gtk.notebookSetTabLabel parent p (Just new)
            else do
              void $ Gtk.notebookAppendPage parent
                                            new
                                            (Nothing :: Maybe Gtk.Widget)
    replaceChild parent _ i old new = do
      let i' = i `div` 2
      pageI <- Gtk.notebookGetNthPage parent i'
      case pageI of
        Nothing -> do
          GLib.logDefaultHandler
            (Just "gi-gtk-declarative")
            [GLib.LogLevelFlagsLevelError]
            (Just
            $ "GI.Gtk.Declarative.Container.Notebook.replaceChild called with an index where there is no child: "
            <> pack (show i)
            )
            nullPtr
        Just p -> do
          if i `mod` 2 == 0
            then do
              label <- Gtk.notebookGetTabLabel parent p -- we have to replace the child
              Gtk.widgetDestroy old
              void $ Gtk.notebookInsertPage parent new label i'
            else do
              Gtk.notebookSetTabLabel parent p (Just new) -- we have to replace the label
  