Saturday, June 12, 2010

Entering numbers

Users of an accounting program need to enter number very often, so I need a bulletproow way to do it.

Numbers are usually entered in text controls, and wxWidgets ha poor native support for this need. I could have written a custom control for my purpose, but I decided that validators are a better solution.
A validator links a C++ variable and the corresponding control. It automatically transfers data between the variable and the control, and it can also validate the input, for example allowing only some characters.

The standard wxTextValidator class links a text control and a wxString variable. An optional wxFILTER_NUMERIC style can be used to only allow numeric input. This looks interesting but it is not enough: the validator only checks keypresses against a static list, so you can type something like "123-34" which is obviously wong. Moreover the handled variable is a wxString that should be manually converted to and from a numerical one.

So I wrote a new validator class, modifying the existing ones. This validator has many enhancements:
  • It links an int or double variable to the text control, with automatic conversion.
  • Keypresses are checked in a way that will always result in a correct numeric value. For example a minus character is only allowed at the beginning of the number.
  • For double variables it is possible to specify a fixed number of decimals.
  • Decimal separator. In my country the decimal separator is the comma (','), but the validator accepts the dot ('.') and converts it to a comma. This is handy because, for example, the numeric keypad does not have a comma key.
Implementing the validator was a relatively straightforward task. In the OnChar() event handler check the arriving keypress, get the control's insertion point with wxTextEntry::GetInsertionPoint() and see how the control's text would look like if the new character were allowed. Decide if the new char can be accepted or not.

The conversion from dot to comma is done swallowing the keypress event and using wxTextTentry::WriteText() to insert the comma.

No comments:

Post a Comment