-- | A combined environment combines a view and a model in a MVC-structured -- application. The environment can be passed around to the controller, which -- must update each side accordingly and keep both in sync. -- -- In this package, the view is built using GTK, and the model is implemented -- as a 'ProtectedModel' (a safe-thread structure with a fine-grained notion -- of change). -- -- Copyright : (C) Keera Studios Ltd, 2013 -- License : BSD3 -- Maintainer : support@keera.co.uk module Hails.MVC.GenericCombinedEnvironment ( -- * Combined Environments (CEnvs) CEnv (view, model) -- * CEnv construction , createCEnv -- * CEnv updates , installCondition , installConditions ) where -- Internal libraries import Hails.MVC.Model.ProtectedModel (ProtectedModel, startProtectedModel) import Hails.MVC.Model.ReactiveModel (Event) import Hails.MVC.View (createView) import Hails.MVC.View.GtkView (GtkGUI, GtkView) -- | Given a GUI and a type for the events that capture the changes inside the -- model, a CEnv contains a view and a protected model. data (GtkGUI a, Event c) => CEnv a b c = CEnv { view :: GtkView a -- ^ View in the CEnv of an MVC application. , model :: ProtectedModel b c -- ^ Model in the CEnv of an MVC application. } -- | Create a combined environment from a given model and initialize the -- model and the view. The default model must be provided explicitly. -- The initialisation operations for the view and the protected model -- are called internally. createCEnv :: (GtkGUI a, Event c) => b -> IO (CEnv a b c) createCEnv emptyBM = CEnv <$> createView <*> startProtectedModel emptyBM -- | Install a condition in a Combined Environment. Conditions, or -- reactive rules, are used to keep both the model and the view -- in sync. -- NOTE: This is an experimental function and might be removed in the future. installCondition :: (GtkGUI a, Event c) => CEnv a b c -> (CEnv a b c -> IO ()) -> IO () installCondition cenv cond = cond cenv -- | Install several conditions in a Combined Environment. Conditions, or -- reactive rules, are used to keep both the model and the view -- in sync. -- FIXME: I really don't like the syntax -- installConditions cenv -- [ rv1 =:= rf1 -- , ... -- ] -- -- I'd rather use -- installConditions cenv $ do -- rv1 =:= rf1 -- rv2 =:= rf2 -- ... -- Which means that I would have to define a monad. -- -- NOTE: This is an experimental function and might be removed in the future. installConditions :: (GtkGUI a, Event c) => CEnv a b c -> [CEnv a b c -> IO ()] -> IO () installConditions cenv conds = mapM_ (installCondition cenv) conds