packages feed

wxhnotepad-1.0.0: src/Step2.hs

-- | 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 ()