There are a range of configuration options that are can be applied to widgets. These are all defined in terms of the Conf type.

\begin{code}
module Conf where
import FranCore
import IOExts
import Monad
import WH
import GUIDef
import qualified StaticTypes as S
import WidgetExports(Config,GUIInfo)
import Compatibility
import Weak
import Identify
import List
\end{code}

The type Config is widget system (such as TclHaskell) dependent and is 
imported abstractly. All other configuration options are functions from
the widget to a GUI action. (Defined for real in GUIDef.lhs)

We can extract the basic and complex config ops using get and withConfigs.

begin{code}

emptyConf :: Conf w
emptyConf = Conf []

newtype Conf w = Conf [ConfItem w]

instance Show (Conf w) where
 show c = "Conf"

data ConfItem w = Config Config | ConfGUI ConfigName (w -> GUI ())

type ConfigName = Ident

end{code}

\begin{code}
-- left overrides right if they are the same
composeConf :: Conf w -> Conf w -> Conf w
composeConf (Conf x) (Conf y) = Conf (union x y)

-- left overrides the right
composeConfs :: [Conf w] -> Conf w
composeConfs cs = foldr composeConf emptyConf cs 

getConfNames :: [Conf w] -> [ConfigName]
getConfNames ws = 
 case composeConfs ws of 
  Conf ws -> map identify ws

\end{code}

\begin{code}

getConfigs :: WidgetItem w => [ConfigName] -> Conf Style -> [Conf w] -> ([Config],w -> GUI ())
getConfigs valids (Conf styles) cs =
 case composeConfs cs of 
   Conf cs -> 
     case getConfigs cs of
      (nms,configs,acts) -> 
	let vs = valids \\ nms 
	    ss = filter (\s -> identify s `elem` vs) styles
        in 
         case getConfigs ss of
          (_,configs2,acts2) -> 
              (configs2 ++ configs,\w -> acts2 (Style w) >> acts w)
 where
  getConfigs cs = foldr getConfig ([],[],const $ return ()) cs

  --getConfig :: Conf w -> ([Config],w -> GUI ()) -> ([Config],w -> GUI ())
  getConfig (Config c) (nms,cs,acts) = (addNm (identify c) nms,c:cs,acts)
  getConfig (ConfGUI n act) (nms,cs,acts) = 
    (addNm n nms,cs,\w -> act w >> acts w)

  addNm :: ConfigName -> [ConfigName] -> [ConfigName]
  addNm n nms | n==nullId = nms
  addNm n nms = n:nms

withConfigs :: WidgetItem w => [ConfigName] -> Conf Style -> [Conf w] -> ([Config] -> GUI w) -> GUI w
withConfigs valids style cs f = 
 case getConfigs valids style cs of 
  (cs,a) -> do
    w <- f cs
    a w
    return w
 
\end{code}

We can define generic configuration options using confGUI and confIO

\begin{code}
confIO :: (w -> IO ()) -> Conf  w
confIO = confIO' nullId

confIO' :: ConfigName -> (w -> IO ()) -> Conf  w
confIO' nm f = Conf [ConfGUI nm $ \g -> liftIO $ f g]

confGUI ::  (w -> GUI ()) -> Conf  w
confGUI = confGUI' nullId

confGUI' :: ConfigName -> (w -> GUI ()) -> Conf  w
confGUI' nm f = Conf [ConfGUI nm f]
 
\end{code}

For instance, the command config action adds an action listener to a widget.
\begin{code}

command :: Has_Action w => Listener () -> Conf w
command l = confGUI  $ \w -> liftIO $ action w l >> return ()

\end{code}
