{-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE RankNTypes #-} -- | The 'StateTree' and 'SomeState' form a "shadow state" -- representation, used in patching. Declarative widgets can return, -- and later on reuse, its underlying GTK+ widget, collected -- properties and classes, style context, custom internal state, and -- child states. This reduces the need for querying GTK+ widgets -- excessively, and recalculating/resetting, greatly improving the -- performance of patching. module GI.Gtk.Declarative.State where import Data.Typeable import Data.Vector (Vector) import qualified GI.Gtk as Gtk import GI.Gtk.Declarative.Attributes.Collected import GI.Gtk.Declarative.Container.Class -- | A 'Data.Dynamic.Dynamic'-like container of a 'StateTree' value. data SomeState where SomeState :: ( Gtk.IsWidget widget , Typeable widget , Typeable customState ) => StateTree stateType widget child event customState -> SomeState -- | The types of state trees that are available, matching the types -- of GTK+ widgets (single widget, bin, and container.) data StateType = WidgetState | BinState | ContainerState -- | A state tree for a specific 'widget'. This is built up recursively -- to contain child state trees, for bin and container child widgets. data StateTree (stateType :: StateType) widget child event customState where StateTreeWidget :: !(StateTreeNode widget event customState) -> StateTree 'WidgetState widget child event customState StateTreeBin :: !(StateTreeNode widget event customState) -> SomeState -> StateTree 'BinState widget child event customState StateTreeContainer :: ( Gtk.IsContainer widget , IsContainer widget child ) => !(StateTreeNode widget event customState) -> Vector SomeState -> StateTree 'ContainerState widget child event customState -- | The common structure for all state tree nodes. data StateTreeNode widget event customState = StateTreeNode { stateTreeWidget :: !widget , stateTreeStyleContext :: !Gtk.StyleContext , stateTreeCollectedAttributes :: !(Collected widget event) , stateTreeCustomState :: customState } -- * Convenience accessor functions -- | Get the common state tree node information. stateTreeNode :: StateTree stateType widget child event customState -> StateTreeNode widget event customState stateTreeNode (StateTreeWidget s ) = s stateTreeNode (StateTreeBin s _) = s stateTreeNode (StateTreeContainer s _) = s -- | Get the specific type of GTK+ widget of a state tree. stateTreeNodeWidget :: StateTree stateType widget child event customState -> widget stateTreeNodeWidget = stateTreeWidget . stateTreeNode -- | Get the GTK+ widget, cast to 'Gtk.Widget', of /some/ state tree. someStateWidget :: SomeState -> IO Gtk.Widget someStateWidget (SomeState st) = Gtk.toWidget (stateTreeNodeWidget st)