-- | This module contains 'MenuType' - a general abstract datatype for menus - -- plus some map-like operations on it. -- -- NBNBNB. 'MenuType' is also used by the graphs and daVinci stuff, which is -- supposed to be independent of HTk. So before making HTk-specific changes -- to this datatype, please find some way of harmlessly ignoring them -- (at best) for daVinci. module HTk.Toolkit.MenuType( MenuPrim(..), -- the general type of menus. -- Map functions mapMenuPrim, -- :: (a -> b) -> MenuPrim c a -> MenuPrim c b mapMenuPrim', -- :: (c -> d) -> MenuPrim c a -> MenuPrim d a mapMMenuPrim, -- :: (Monad m) => (a -> m b) -> MenuPrim c a -- -> m (MenuPrim c b) mapMMenuPrim', -- :: (Monad m) => (c -> m d) -> MenuPrim c a -- -> m (MenuPrim d a) ) where -- ---------------------------------------------------------------------- -- General basic Menu type. -- For particular applications, for example HTk menus, it is recommended -- that we wrap MenuPrim inside a newtype, for example -- newtype HTkMenu value = HTkMenu (MenuPrim (Maybe String) value) -- Different applications will need different values for both the -- typevariables subMenuValue and value; for example daVinci uses a -- value of subMenuValue which isn't Maybe String while it is compiling -- menus. -- ---------------------------------------------------------------------- data MenuPrim subMenuValue value = Button String value -- A button with the given (String) label | Menu subMenuValue [MenuPrim subMenuValue value] -- A list of buttons (or further menus) inside a menu | Blank -- A Blank can be used to separate groups of menu buttons in the -- same menu. -- ---------------------------------------------------------------------- -- Map functions -- There are 4 of these, for each possible answer to the two questions -- (1) map or monadic map? -- (2) map first type or second type? -- ---------------------------------------------------------------------- mapMenuPrim :: (a -> b) -> MenuPrim c a -> MenuPrim c b mapMenuPrim a2b (Button label a) = Button label (a2b a) mapMenuPrim a2b (Menu subMenuValue menuButtons) = Menu subMenuValue (map (mapMenuPrim a2b) menuButtons) mapMenuPrim a2b Blank = Blank mapMenuPrim' :: (c -> d) -> MenuPrim c a -> MenuPrim d a mapMenuPrim' c2d (Button title action) = Button title action mapMenuPrim' c2d (Menu subMenuValue menuButtons) = Menu (c2d subMenuValue) (map (mapMenuPrim' c2d) menuButtons) mapMenuPrim' c2d Blank = Blank mapMMenuPrim :: (Monad m) => (a -> m b) -> MenuPrim c a -> m (MenuPrim c b) mapMMenuPrim a2bAct (Button label a) = do b <- a2bAct a return (Button label b) mapMMenuPrim a2bAct (Menu subMenuValue menuButtons) = do bMenuButtons <- mapM (mapMMenuPrim a2bAct) menuButtons return (Menu subMenuValue bMenuButtons) mapMMenuPrim a2bAct Blank = return Blank mapMMenuPrim' :: (Monad m) => (c -> m d) -> MenuPrim c a -> m (MenuPrim d a) mapMMenuPrim' c2dAct (Button title action) = return (Button title action) mapMMenuPrim' c2dAct (Menu subMenuValue menuButtons) = do dMenuButtons <- mapM (mapMMenuPrim' c2dAct) menuButtons dSubMenuValue <- c2dAct subMenuValue return (Menu dSubMenuValue dMenuButtons) mapMMenuPrim' c2dAct Blank = return Blank