moduleSifflet.UI.Callback(CBMgr,CBMgrCmd(..),mkCBMgr,MenuSpec(..),MenuItemSpec(..),MenuItemAction,createMenuBar,addMenu,createMenu,createMenuItem,modifyIORefIO)whereimportData.IORefimportGraphics.UI.GtkimportSifflet.UI.Types-- | The CBMgr (Callback manager) encapsulates (in an enclosure, no less!)-- an IORef VPUI. It is used *solely* to set up callbacks-- and similar stuff in Gtk, where the callback needs access-- to the IORef. By passing a CBMgr to a function, we can-- avoid passing the IORef directly, and all the harm and-- confusion that could result.---- We only need *one* CBMgr for the application;-- however, two CBMgrs with the same IORef are logically equivalent,-- so there would be no harm in having two as long as they share one IORef.typeCBMgr=CBMgrCmd->IO()-- | Commands for the CBMgrdataCBMgrCmd=-- window eventsOnWindowConfigureWindow(IORefVPUI->EventMEConfigureBool)|OnWindowDestroyWindow(IORefVPUI->IO())|OnWindowKeyPressWindow(IORefVPUI->EventMEKeyBool)-- layout events|OnLayoutExposeLayout(IORefVPUI->EventMEExposeBool)|OnLayoutMouseMoveLayout(IORefVPUI->EventMEMotionBool)|OnLayoutButtonPressLayout(IORefVPUI->EventMEButtonBool)|OnLayoutButtonReleaseLayout(IORefVPUI->EventMEButtonBool)-- other events|OnMenuItemActivateLeafMenuItem(VPUI->IOVPUI)|OnEntryActivateEntry(IORefVPUI->IO())|AfterButtonClickedButton(IORefVPUI->IO())|UMTest-- | Create the CBMgrmkCBMgr::IORefVPUI->CBMgrmkCBMgruirefcmd=casecmdof-- window eventsOnWindowConfigurewindowaction->onwindowconfigureEvent(actionuiref)>>return()OnWindowDestroywindowaction->onDestroywindow(actionuiref)>>return()OnWindowKeyPresswindowaction->onwindowkeyPressEvent(actionuiref)>>return()-- layout eventsOnLayoutExposelayoutaction->onlayoutexposeEvent(actionuiref)>>return()OnLayoutMouseMovelayoutaction->onlayoutmotionNotifyEvent(actionuiref)>>return()OnLayoutButtonPresslayoutaction->onlayoutbuttonPressEvent(actionuiref)>>return()OnLayoutButtonReleaselayoutaction->onlayoutbuttonReleaseEvent(actionuiref)>>return()-- other eventsOnMenuItemActivateLeafmenuItemaction->onActivateLeafmenuItem(modifyIORefIOuirefaction)>>return()OnEntryActivateentryaction->onEntryActivateentry(actionuiref)>>return()AfterButtonClickedbuttonaction->afterClickedbutton(actionuiref)>>return()UMTest->putStrLn"UMTest"-- ============================================================-- MENUS-- Easy creation of menus from lists.-- Originally from ~/src/haskell-etudes/gtk2hs/gMenu.hsdataMenuSpec=MenuSpecString[MenuItemSpec]dataMenuItemSpec=MenuItemStringMenuItemAction|SubMenuMenuSpectypeMenuItemAction=VPUI->IOVPUI-- was just IO ()createMenuBar::[MenuSpec]->CBMgr->IOMenuBarcreateMenuBarmenuSpecscbmgr=dobar<-menuBarNewmapM_(addMenubarcbmgr)menuSpecsreturnbaraddMenu::MenuBar->CBMgr->MenuSpec->IO()addMenumbarcbmgrmspec@(MenuSpecname_itemSpecs)=domenuHead<-menuItemNewWithLabelname-- visible "item" at top of the menumenuShellAppendmbarmenuHead-- Right-justify help menu.-- Deprecated (bad for right-to-left languages),-- but retained for compatibility with menus_hard.py.menuItemSetRightJustifiedmenuHead(name=="Help")-- ??????-- menu = the container for menu itemsmenu<-createMenumspeccbmgrmenuItemSetSubmenumenuHeadmenucreateMenu::MenuSpec->CBMgr->IOMenucreateMenu(MenuSpec_nameitemSpecs)cbmgr=domenu<-menuNewmapM_(createMenuItemmenucbmgr)itemSpecsreturnmenucreateMenuItem::Menu->CBMgr->MenuItemSpec->IO()createMenuItemmenucbmgrmispec=casemispecofMenuItemlabelaction->do{item<-menuItemNewWithLabellabel;cbmgr(OnMenuItemActivateLeafitemaction)-- may need to read/write IORef here ***;menuShellAppendmenuitem}SubMenusubspec@(MenuSpeclabel_itemSpecs)->do{item<-menuItemNewWithLabellabel;submenu<-createMenusubspeccbmgr;menuItemSetSubmenuitemsubmenu;menuShellAppendmenuitem}-- | Read an IORef, update with IO, and write the updated value.-- This is like modifyIORef, but the type of the second argument is (a -> IO a)-- instead of (a -> a).modifyIORefIO::IORefa->(a->IOa)->IO()modifyIORefIOrefupdateIO=readIORefref>>=updateIO>>=writeIORefref