{-# OPTIONS_GHC -fno-warn-unticked-promoted-constructors #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module GI.Gtk.Declarative.Bin
( Bin(..)
, bin
)
where
import Data.Typeable
import Data.Vector (Vector)
import qualified GI.Gtk as Gtk
import GI.Gtk.Declarative.Attributes
import GI.Gtk.Declarative.Attributes.Collected
import GI.Gtk.Declarative.Attributes.Internal
import GI.Gtk.Declarative.EventSource
import GI.Gtk.Declarative.Patch
import GI.Gtk.Declarative.State
import GI.Gtk.Declarative.Widget
data Bin widget event where
Bin
:: ( Typeable widget
, Gtk.IsContainer widget
, Gtk.IsBin widget
, Gtk.IsWidget widget
)
=> (Gtk.ManagedPtr widget -> widget)
-> Vector (Attribute widget event)
-> Widget event
-> Bin widget event
instance Functor (Bin widget) where
fmap f (Bin ctor attrs child) =
Bin ctor (fmap f <$> attrs) (fmap f child)
bin
:: ( Patchable (Bin widget)
, Typeable widget
, Typeable event
, Gtk.IsContainer widget
, Gtk.IsBin widget
, Gtk.IsWidget widget
, FromWidget (Bin widget) target
)
=> (Gtk.ManagedPtr widget -> widget)
-> Vector (Attribute widget event)
-> Widget event
-> target event
bin ctor attrs = fromWidget . Bin ctor attrs
instance (Gtk.IsBin parent) => Patchable (Bin parent) where
create (Bin (ctor :: Gtk.ManagedPtr w -> w) attrs child) = do
let collected = collectAttributes attrs
widget' <- Gtk.new ctor (constructProperties collected)
Gtk.widgetShow widget'
sc <- Gtk.widgetGetStyleContext widget'
updateClasses sc mempty (collectedClasses collected)
mapM_ (applyAfterCreated widget') attrs
childState <- create child
childWidget <- someStateWidget childState
maybe (pure ()) Gtk.widgetDestroy =<< Gtk.binGetChild widget'
Gtk.containerAdd widget' childWidget
return (SomeState (StateTreeBin (StateTreeNode widget' sc collected ()) childState))
patch (SomeState (st :: StateTree stateType w1 c1 e1 cs))
(Bin _ _ oldChild)
(Bin (ctor :: Gtk.ManagedPtr w2 -> w2) newAttributes newChild) =
case (st, eqT @w1 @w2) of
(StateTreeBin top oldChildState, Just Refl) ->
Modify $ do
binWidget <- Gtk.unsafeCastTo ctor (stateTreeWidget top)
let oldCollected = stateTreeCollectedAttributes top
newCollected = collectAttributes newAttributes
updateProperties binWidget (collectedProperties oldCollected) (collectedProperties newCollected)
updateClasses (stateTreeStyleContext top) (collectedClasses oldCollected) (collectedClasses newCollected)
let top' = top { stateTreeCollectedAttributes = newCollected }
case patch oldChildState oldChild newChild of
Modify modify -> SomeState . StateTreeBin top' <$> modify
Replace createNew -> do
Gtk.widgetDestroy =<< someStateWidget oldChildState
newChildState <- createNew
childWidget <- someStateWidget newChildState
Gtk.widgetShow childWidget
maybe (pure ()) Gtk.widgetDestroy =<< Gtk.binGetChild binWidget
Gtk.containerAdd binWidget childWidget
return (SomeState (StateTreeBin top' newChildState))
Keep -> return (SomeState st)
_ -> Replace (create (Bin ctor newAttributes newChild))
instance Gtk.IsBin parent => EventSource (Bin parent) where
subscribe (Bin ctor props child) (SomeState st) cb =
case st of
StateTreeBin top childState -> do
binWidget <- Gtk.unsafeCastTo ctor (stateTreeWidget top)
handlers' <- foldMap (addSignalHandler cb binWidget) props
(<> handlers') <$> subscribe child childState cb
_ -> error "Cannot subscribe to Bin events with a non-bin state tree."
instance a ~ b => FromWidget (Bin a) (Bin b) where
fromWidget = id