| 1 | \section{wxValidator overview}\label{validatoroverview} |
| 2 | |
| 3 | Classes: \helpref{wxValidator}{wxvalidator}, \helpref{wxTextValidator}{wxtextvalidator}, |
| 4 | \helpref{wxGenericValidator}{wxgenericvalidator} |
| 5 | |
| 6 | The aim of the validator concept is to make dialogs very much easier to write. |
| 7 | A validator is an object that can be plugged into a control (such as a wxTextCtrl), and |
| 8 | mediates between C++ data and the control, transferring the data in either direction |
| 9 | and validating it. It also is able to intercept events generated |
| 10 | by the control, providing filtering behaviour without the need to derive a new control class. |
| 11 | |
| 12 | You can use a stock validator, such as \helpref{wxTextValidator}{wxtextvalidator} (which does text |
| 13 | control data transfer, validation and filtering) and |
| 14 | \helpref{wxGenericValidator}{wxgenericvalidator} (which does data transfer for a range of controls); |
| 15 | or you can write your own. |
| 16 | |
| 17 | \wxheading{Example} |
| 18 | |
| 19 | Here is an example of wxTextValidator usage. |
| 20 | |
| 21 | \begin{verbatim} |
| 22 | wxTextCtrl *txt1 = new wxTextCtrl(this, -1, wxT(""), |
| 23 | wxPoint(10, 10), wxSize(100, 80), 0, |
| 24 | wxTextValidator(wxFILTER_ALPHA, &g_data.m_string)); |
| 25 | \end{verbatim} |
| 26 | |
| 27 | In this example, the text validator object provides the following functionality: |
| 28 | |
| 29 | \begin{enumerate}\itemsep=0pt |
| 30 | \item It transfers the value of g\_data.m\_string (a wxString variable) to the wxTextCtrl when |
| 31 | the dialog is initialised. |
| 32 | \item It transfers the wxTextCtrl data back to this variable when the dialog is dismissed. |
| 33 | \item It filters input characters so that only alphabetic characters are allowed. |
| 34 | \end{enumerate} |
| 35 | |
| 36 | The validation and filtering of input is accomplished in two ways. When a character is input, |
| 37 | wxTextValidator checks the character against the allowed filter flag (wxFILTER\_ALPHA in this case). If |
| 38 | the character is inappropriate, it is vetoed (does not appear) and a warning beep sounds. |
| 39 | The second type of validation is performed when the dialog is about to be dismissed, so if |
| 40 | the default string contained invalid characters already, a dialog box is shown giving the |
| 41 | error, and the dialog is not dismissed. |
| 42 | |
| 43 | \wxheading{Anatomy of a validator} |
| 44 | |
| 45 | A programmer creating a new validator class should provide the following functionality. |
| 46 | |
| 47 | A validator constructor is responsible for allowing the programmer to specify the kind |
| 48 | of validation required, and perhaps a pointer to a C++ variable that is used for storing the |
| 49 | data for the control. If such a variable address is not supplied by the user, then |
| 50 | the validator should store the data internally. |
| 51 | |
| 52 | The \helpref{wxValidator::Validate}{wxvalidatorvalidate} member function should return |
| 53 | true if the data in the control (not the C++ variable) is valid. It should also show |
| 54 | an appropriate message if data was not valid. |
| 55 | |
| 56 | The \helpref{wxValidator::TransferToWindow}{wxvalidatortransfertowindow} member function should |
| 57 | transfer the data from the validator or associated C++ variable to the control. |
| 58 | |
| 59 | The \helpref{wxValidator::TransferFromWindow}{wxvalidatortransferfromwindow} member function should |
| 60 | transfer the data from the control to the validator or associated C++ variable. |
| 61 | |
| 62 | There should be a copy constructor, and a \helpref{wxValidator::Clone}{wxvalidatorclone} function |
| 63 | which returns a copy of the validator object. This is important because validators |
| 64 | are passed by reference to window constructors, and must therefore be cloned internally. |
| 65 | |
| 66 | You can optionally define event handlers for the validator, to implement filtering. These handlers |
| 67 | will capture events before the control itself does. |
| 68 | |
| 69 | For an example implementation, see the valtext.h and valtext.cpp files in the wxWidgets library. |
| 70 | |
| 71 | \wxheading{How validators interact with dialogs} |
| 72 | |
| 73 | For validators to work correctly, validator functions must be called at the right times during |
| 74 | dialog initialisation and dismissal. |
| 75 | |
| 76 | When a \helpref{wxDialog::Show}{wxdialogshow} is called (for a modeless dialog) |
| 77 | or \helpref{wxDialog::ShowModal}{wxdialogshowmodal} is called (for a modal dialog), |
| 78 | the function \helpref{wxWindow::InitDialog}{wxwindowinitdialog} is automatically called. |
| 79 | This in turn sends an initialisation event to the dialog. The default handler for |
| 80 | the wxEVT\_INIT\_DIALOG event is defined in the wxWindow class to simply call |
| 81 | the function \helpref{wxWindow::TransferDataToWindow}{wxwindowtransferdatatowindow}. This |
| 82 | function finds all the validators in the window's children and calls the TransferToWindow |
| 83 | function for each. Thus, data is transferred from C++ variables to the dialog |
| 84 | just as the dialog is being shown. |
| 85 | |
| 86 | \normalbox{If you are using a window or panel instead of a dialog, you will need to |
| 87 | call \helpref{wxWindow::InitDialog}{wxwindowinitdialog} explicitly before showing the |
| 88 | window.} |
| 89 | |
| 90 | When the user clicks on a button, for example the OK button, the application should |
| 91 | first call \helpref{wxWindow::Validate}{wxwindowvalidate}, which returns false if |
| 92 | any of the child window validators failed to validate the window data. The button handler |
| 93 | should return immediately if validation failed. Secondly, the application should |
| 94 | call \helpref{wxWindow::TransferDataFromWindow}{wxwindowtransferdatafromwindow} and |
| 95 | return if this failed. It is then safe to end the dialog by calling EndModal (if modal) |
| 96 | or Show (if modeless). |
| 97 | |
| 98 | In fact, wxDialog contains a default command event handler for the wxID\_OK button. It goes like |
| 99 | this: |
| 100 | |
| 101 | \begin{verbatim} |
| 102 | void wxDialog::OnOK(wxCommandEvent& event) |
| 103 | { |
| 104 | if ( Validate() && TransferDataFromWindow() ) |
| 105 | { |
| 106 | if ( IsModal() ) |
| 107 | EndModal(wxID_OK); |
| 108 | else |
| 109 | { |
| 110 | SetReturnCode(wxID_OK); |
| 111 | this->Show(false); |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | \end{verbatim} |
| 116 | |
| 117 | So if using validators and a normal OK button, you may not even need to write any |
| 118 | code for handling dialog dismissal. |
| 119 | |
| 120 | If you load your dialog from a resource file, you will need to iterate through the controls |
| 121 | setting validators, since validators can't be specified in a dialog resource. |
| 122 | |