-- | Publishes the main elements of a scale as reactive fields module Graphics.UI.Gtk.Reactive.Property where import Control.Monad (void, when) import Graphics.UI.Gtk import Data.ReactiveValue -- * Attributes as reactive values -- ** Signal-based reactimation functions. -- | Create an RV based on a widget's attribute and signal. Before setting, -- the value is checked against the current one. If they are the same, the -- value is *not* set. reactiveProperty :: Eq b => self -> Signal self (IO ()) -> Attr self b -> ReactiveFieldReadWrite IO b reactiveProperty e sig attr = ReactiveFieldReadWrite setter getter notifier where getter = get e attr setter v = postGUIAsync $ do p <- getter when (p /= v) $ set e [ attr := v ] notifier p = void (on e sig p) -- | Create an RV based on a widget's attribute and signal. -- Before setting, the value is *not* checked against the current one. -- The value is thus set even if they are the same. reactivePropertyNE :: self -> Signal self (IO ()) -> Attr self b -> ReactiveFieldReadWrite IO b reactivePropertyNE e sig attr = ReactiveFieldReadWrite setter getter notifier where getter = get e attr setter v = postGUIAsync $ set e [ attr := v ] notifier p = void (on e sig p) -- ** Handler-based reactimation functions -- | Create an RV based on a widget's attribute and a handler. -- Before setting, the value is checked against the current one. -- If they are the same, the value is *not* set. reactivePropertyH :: Eq b => self -> (self -> IO () -> IO (ConnectId self)) -> Attr self b -> ReactiveFieldReadWrite IO b reactivePropertyH e sig attr = ReactiveFieldReadWrite setter getter notifier where getter = get e attr setter v = postGUIAsync $ do p <- getter when (p /= v) $ set e [ attr := v ] notifier p = void (e `sig` p) -- * Passive properties -- | A passive reactive value is one that does not report when it changes. -- -- This function returns a RW RV that encloses the given property, without -- firing change events. The value of the attribute is *not* set if it is the -- same as the current one. -- -- To set without diffing, see 'passivePropertyNE'. passiveProperty :: Eq b => self -> Attr self b -> ReactiveFieldReadWrite IO b passiveProperty e attr = ReactiveFieldReadWrite setter getter notifier where getter = get e attr setter v = postGUIAsync $ do p <- getter when (p /= v) $ set e [ attr := v ] notifier _ = return () -- | Return a RW RV that encloses the given property, without firing change -- events. -- -- When writing to this RV, the value is *not* diffed against the previous one. -- The underlying widget can thus still fire signals based on that change. passivePropertyNE :: self -> Attr self b -> ReactiveFieldReadWrite IO b passivePropertyNE e attr = ReactiveFieldReadWrite setter getter notifier where getter = get e attr setter v = postGUIAsync $ set e [ attr := v ] notifier _ = return ()