Building a text editor (Part 4)

In this very short post we add copy/cut/paste support to the editor. These will be accessible from the menu as well as by using the usual CUA keystrokes (Ctrl-C, Ctrl-X, Ctrl-V).

Most of the required functionality is provided by the TextCtrl itself, so the code mainly consists of connecting up event handlers to bind to the TextCtrl functions.

The first issue we need to deal with is a wxHaskell bug – this will be fixed shortly, but in the meantime it is worth knowing about. The problem is that wxHaskellprovides the wrong constants for wxID_CUT, wxID_COPY and wxID_PASTE, which are the standard identifiers used by the text control.

As always, changed text id highlighted in red.

 > import Graphics.UI.WXCore hiding (wxID_CUT, wxID_COPY, wxID_PASTE)

We can now put the correct values in ourselves. These are ‘magic’ numbers, and you’ll have to trust me that they are correct – it is not particularly easy to work out the correct values without wading through lots of C++ code.

 > wxID_MYUNDO, wxID_MYREDO, wxID_CUT, wxID_COPY, wxID_PASTE :: Id
 > wxID_MYUNDO = 5107
 > wxID_MYREDO = 5108
 > wxID_CUT    = 5031
 > wxID_COPY   = 5032
 > wxID_PASTE  = 5033

We now add the menu items and their event handlers. Nothing new here: we’ve looked at menus before. These go into the GUI top level function, along with the other UI component definitions.

 > menuAppendSeparator mnuEdit
 > menuAppend mnuEdit wxID_CUT "C&ut\tCtrl-x" "Cut" False
 > menuAppend mnuEdit wxID_COPY "&Copy\tCtrl-c" "Copy" False
 > menuAppend mnuEdit wxID_PASTE "&Paste\tCtrl-v" "Paste" False

 > evtHandlerOnMenuCommand win wxID_CUT $ cut guiCtx
 > evtHandlerOnMenuCommand win wxID_COPY $ copy guiCtx
 > evtHandlerOnMenuCommand win wxID_PASTE $ paste guiCtx

We also require three new event handler functions:

— We just copy the selected text

The copy function simply uses the textCtrlCopy function provided by the control. Remember (see part 2) that we use GUICtx as a way to pass around the global state (the GUI widgets).

 > copy GUICtx{guiEditor = editor} =
 >   textCtrlCopy editor

The cut function also uses the standard editor functionality, but in this case we are modifying the contents of the TextCtrl and we must update the GUI with an undo action.

 > cut guiCtx@GUICtx{guiEditor = editor} =
 >   textCtrlCut editor >> updatePast guiCtx

The paste function also modifies the undo history.

 > paste guiCtx@GUICtx{guiEditor = editor} =
 >   textCtrlPaste editor >> updatePast guiCtx

Leave a comment