Occasionally it is useful not to close a window immediately but to ask the user to confirm the close request. To do that, you have to provide a handler for the deleteEvent of your window. That handler is required to have the type
Window -> IO Bool
or
Window -> EventM EAny Bool
The return value of that handler indicates whether or not the user allows to close the window.
The handler itself opens a dialog window to obtain a decision.
Archive file with this example: Example003.tar.gz. Be sure to read the file README.txt for further instructions.
import "gtk3" Graphics.UI.Gtk import "gtk3" Graphics.UI.Gtk.Gdk.Events import Control.Monad.IO.Class -- for liftIO -- This function handles the delete event. The delete event is -- vetoable; the event handler is required to return a logical -- value to indicate whether the event handling should be continued -- or aborted. -- Possible result values of this funtion: -- True : do not continue event handling. This will keep -- the window. -- False : continue event handling. This will close and -- destroy the window. -- This handler displays a confirmer to decide how to proceed. -- deleteEventHandler :: Window -> IO Bool deleteEventHandler transientParentWindow = do dialog <- messageDialogNew (Just transientParentWindow) [DialogDestroyWithParent] MessageQuestion ButtonsYesNo "Do you want to close this window ?" set dialog [windowTitle := "About to close"] result <- dialogRun dialog widgetDestroy dialog if result == ResponseYes then return False else return True -- This function is to be called when the window is destroyed. -- The function has the responsibility to terminate the program -- in an orderly way. It does so in exiting the event loop. destroyEventHandler :: IO () destroyEventHandler = do mainQuit -- main program: create and display the window main :: IO () main = do initGUI -- all needed widgets are created window <- windowNew -- the properties of the main window are set set window [windowDefaultWidth := 250, -- initial window size windowDefaultHeight := 280, widgetWidthRequest := 100, -- minimal window size widgetHeightRequest := 80, windowWindowPosition := WinPosCenter, windowTitle := "Example 3"] -- all needed callback functions are provided on window deleteEvent $ liftIO (deleteEventHandler window) on window objectDestroy destroyEventHandler -- all widgets are made visible widgetShow window -- the event processing is started mainGUI
It is possible to write the event handler for the deleteEvent in a slightly different manner:
deleteEventHandler :: Window -> IO Bool deleteEventHandler transientParentWindow = do dialog <- messageDialogNew (Just transientParentWindow) [DialogDestroyWithParent] MessageQuestion ButtonsYesNo "Do you want to close this window ?" set dialog [windowTitle := "About to close"] result <- dialogRun dialog widgetDestroy dialog let answer = result == ResponseNo return answer
import "gtk3" Graphics.UI.Gtk import "gtk3" Graphics.UI.Gtk.Gdk.Events import Control.Monad.IO.Class -- for liftIO -- This function handles the delete event. The delete event is -- vetoable; the event handler is required to return a logical -- value to indicate whether the event handling should be continued -- or aborted. -- Possible result values of this funtion: -- True : do not continue event handling. This will keep -- the window. -- False : continue event handling. This will close and -- destroy the window. -- This handler displays a confirmer to decide how to proceed. -- deleteEventHandler :: Window -> EventM EAny Bool deleteEventHandler transientParentWindow = liftIO $ do dialog <- messageDialogNew (Just transientParentWindow) [DialogDestroyWithParent] MessageQuestion ButtonsYesNo "Do you want to close this window ?" set dialog [windowTitle := "About to close"] result <- dialogRun dialog widgetDestroy dialog if result == ResponseYes then return False -- continue event handling, close and destroy the window else return True -- event handling is now complete, do not continue -- This function is to be called when the window is destroyed. -- The function has the responsibility to terminate the program -- in an orderly way. It does so in exiting the event loop. destroyEventHandler :: IO () destroyEventHandler = do mainQuit -- main program: create and display the window main :: IO () main = do initGUI -- all needed widgets are created window <- windowNew -- the properties of the main window are set set window [windowDefaultWidth := 250, windowDefaultHeight := 280, widgetWidthRequest := 100, widgetHeightRequest := 80, windowWindowPosition := WinPosCenterAlways, windowTitle := "Example 3"] -- all needed callback functions are provided on window deleteEvent (deleteEventHandler window) on window objectDestroy destroyEventHandler -- all widgets are made visible widgetShow window -- the event processing is started mainGUI