-- | Like Step1 but with Open / Save / Save As... support module Step2 (step2) where import Graphics.UI.WX import Graphics.UI.WXCore -- | We create a record for the context to simplify parameter passing in al event -- handlers. It seems pretty useless now, but you'll see this purpose later data GUIContext = GUICtx { guiWin :: Frame (), guiEditor :: TextCtrl (), guiFile :: Var (Maybe FilePath) -- ^ The path of the current file } step2 :: IO () step2 = do win <- frame [text := "wxhNotepad - Step 2", visible := False] editor <- textCtrl win [font := fontFixed, text := "Now the user can open a file, save it" ++ "or save it with another name.\n" ++ "Our program is smart enough to remember" ++ "the path of the last opened/saved file\n" ++ "Note that we're *not* catching any " ++ "filesystem errors here. That's left " ++ "as a homework for you :P"] filePath <- varCreate Nothing -- We define the context to use it on every event handling function let guiCtx = GUICtx win editor filePath -- We create a menu for the window with the three items we want to add mnuFile <- menuPane [text := "File"] -- Just for fun, we use WXCore methods instead of WX ones menuAppend mnuFile wxID_OPEN "&Open...\tCtrl-o" "Open Page" False menuAppend mnuFile wxID_SAVE "&Save\tCtrl-s" "Save Page" False menuAppend mnuFile wxID_SAVEAS "Save &as...\tCtrl-Shift-s" "Save Page as" False menuAppend mnuFile wxID_CLOSE "&Close\tCtrl-W" "Close Page" False -- We associate the corresponding action to each menuItem -- the actions are defined below in this module evtHandlerOnMenuCommand win wxID_OPEN $ openPage guiCtx evtHandlerOnMenuCommand win wxID_SAVE $ savePage guiCtx evtHandlerOnMenuCommand win wxID_SAVEAS $ savePageAs guiCtx evtHandlerOnMenuCommand win wxID_CLOSE $ windowClose win False >> return () -- And finally we add the bar to the window set win [menuBar := [mnuFile]] set win [layout := fill $ widget editor, clientSize := sz 640 480] focusOn editor set win [visible := True] savePageAs, savePage, openPage :: GUIContext -> IO () openPage GUICtx{guiWin = win, guiEditor = editor, guiFile = filePath} = do -- WXCore provides a couple of useful dialog methods, like this one. -- see: http://hackage.haskell.org/packages/archive/wxcore/latest/doc/html/Graphics-UI-WXCore-Dialogs.html#3 maybePath <- fileOpenDialog win True True "Open file..." [("Haskells (*.hs)",["*.hs"]), ("Texts (*.txt)", ["*.txt"]), ("Any file (*.*)",["*.*"])] "" "" case maybePath of Nothing -> -- The user cancelled... nothing to do return () Just path -> do -- We put the text on the box textCtrlLoadFile editor path -- Usually, you want to see the name of the file in the window title set win [text := "wxhnotepad - " ++ path] -- and set the path in our variable varSet filePath $ Just path savePageAs GUICtx{guiWin = win, guiEditor = editor, guiFile = filePath} = do -- WXCore provides a couple of useful dialog methods, like this one. -- see: http://hackage.haskell.org/packages/archive/wxcore/latest/doc/html/Graphics-UI-WXCore-Dialogs.html#v%3AfileSaveDialog maybePath <- fileSaveDialog win True True "Save file..." [("Haskells (*.hs)",["*.hs"]), ("Texts (*.txt)", ["*.txt"]), ("Any file (*.*)",["*.*"])] "" "" case maybePath of Nothing -> -- The user cancelled... nothing to do return () Just path -> do -- We send the text to the file... textCtrlSaveFile editor path -- Usually, you want to see the name of the file in the window title set win [text := "wxhnotepad - " ++ path] -- and set the path in our variable varSet filePath $ Just path savePage guiCtx@GUICtx{guiWin = win, guiEditor = editor, guiFile = filePath} = do maybePath <- varGet filePath case maybePath of Nothing -> savePageAs guiCtx Just path -> -- We just send the text to the file... textCtrlSaveFile editor path >> return ()