gi-gtk-declarative-0.3.0: src/GI/Gtk/Declarative/SingleWidget.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
-- | A declarative representation of 'Gtk.Widget' in GTK without children.
module GI.Gtk.Declarative.SingleWidget
( SingleWidget
, widget
)
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
-- | Declarative version of a /leaf/ widget, i.e. a widget without any children.
data SingleWidget widget event where
SingleWidget
:: (Typeable widget, Gtk.IsWidget widget, Functor (Attribute widget))
=> (Gtk.ManagedPtr widget -> widget)
-> Vector (Attribute widget event)
-> SingleWidget widget event
instance Functor (SingleWidget widget) where
fmap f (SingleWidget ctor attrs) = SingleWidget ctor (fmap f <$> attrs)
instance Patchable (SingleWidget widget) where
create = \case
SingleWidget ctor attrs -> 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
return (SomeState (StateTreeWidget (StateTreeNode widget' sc collected ())))
patch (SomeState (st :: StateTree stateType w child event cs))
(SingleWidget (_ :: Gtk.ManagedPtr w1 -> w1) _)
(SingleWidget (ctor :: Gtk.ManagedPtr w2 -> w2) newAttributes) =
case (st, eqT @w @w1, eqT @w1 @w2) of
(StateTreeWidget top, Just Refl, Just Refl) -> Modify $ do
let w = stateTreeWidget top
let oldCollected = stateTreeCollectedAttributes top
newCollected = collectAttributes newAttributes
updateProperties w (collectedProperties oldCollected) (collectedProperties newCollected)
updateClasses (stateTreeStyleContext top) (collectedClasses oldCollected) (collectedClasses newCollected)
let top' = top { stateTreeCollectedAttributes = newCollected }
return (SomeState (StateTreeWidget top' { stateTreeCollectedAttributes = newCollected }))
_ -> Replace (create (SingleWidget ctor newAttributes))
instance EventSource (SingleWidget widget) where
subscribe (SingleWidget (_ :: Gtk.ManagedPtr w1 -> w1) props) (SomeState (st :: StateTree stateType w2 child event cs)) cb =
case (st, eqT @w1 @w2) of
(StateTreeWidget top, Just Refl) ->
foldMap (addSignalHandler cb (stateTreeWidget top)) props
_ -> fail ""
-- instance (Typeable widget, Functor (SingleWidget widget))
-- => FromWidget (SingleWidget widget) Widget where
-- fromWidget = Widget
-- | Construct a /leaf/ widget, i.e. one without any children.
widget
:: ( Typeable widget
, Typeable event
, Functor (Attribute widget)
, Gtk.IsWidget widget
, FromWidget (SingleWidget widget) target
)
=> (Gtk.ManagedPtr widget -> widget) -- ^ A widget constructor from the underlying gi-gtk library.
-> Vector (Attribute widget event) -- ^ List of 'Attribute's.
-> target event -- ^ The target, whose type is decided by 'FromWidget'.
widget ctor = fromWidget . SingleWidget ctor