wxMaskedEditCtrl possible revival

245 views
Skip to first unread message

Manolo

unread,
May 24, 2012, 7:59:53 PM5/24/12
to wx-...@googlegroups.com
Hi
I'm thinking of giving wxMaskedEditCtrl a try.

I found:
http://svn.wxwidgets.org/viewvc/wx/wxWidgets/branches/SOC2010_MASKED_CTRL/interface/wx/maskededit.h
and
http://wxpython.org/docs/api/wx.lib.masked.maskededit-module.html

After reading those docs, I still have some thoughts and doubts:

a) This is not a composite control, just an "edit control" which
allows only some kind of inputs.
Something similar to a wxValidator. Or, should it really be a
specialized validator?

b) It shall work with wxTextCtrl and wxComboBox. I guess, with wxTextEntry.

c) The whole string at the control is divided into one or more
"fields", with something to
separate them. This "something separator" is given in the mask.
Example 1: "123.123.123.123" the separator is "."
Example 2: "12-mar-2012" the separator is "-"
Example 3: "04/10 23:15" with three separators "/", " " and ":"
Example 4: "(090)123123" with a prefix "(" and a separator ")"

d) Mask characters, or "what this control is said to do"
# Allow numeric only (0-9)
N Allow letters and numbers (0-9)
A Allow uppercase letters only
a Allow lowercase letters only
C Allow any letter, upper or lower
It should be advised that uppercase/lowercase works well currently
just with latin characters.
X Allow string.letters, string.punctuation, string.digits
& Allow string.punctuation only (doesn't include all unicode symbols)
* Allow any visible character
What's intended with "punctuation"? Any other character like @#'<;?
What is a "visible" character?
| Field boundary. Fields are continuous, without separator between them
Is this "|" mandatory?

All these "allow" characters mean you can type it, or not. But it
lacks a "you must" type it.
If I need a four, not other than four, characters field, how is this
told in the mask?

e) Literal characters may be set. So, with a mask like "##\a#.###"
valid inputs are "12a3.456"
or "45a1.900". How many fields are here? two: "12a3" and "456" or
three: "12" "a3" and "456"
And, if that "." is considered as a field separator, shouldn't that
"\a" be a field separator too?
Literals, must the user type them?

f) Format codes:
_ Allow spaces
! Force upper
^ Force lower
R Right-align field(s)
r Right-insert in field(s) (implies R)
< Stay in field until explicit navigation out of it
I don't understand this "<"
> insert/delete/backspace behaviour.
As I understand this, delete/backspace-key can delete a char or the whole field.
F Auto-Fit: The control calculate its size from the mask length.
What is this needed for? wxWindow::SetMinSize()? If so, a fixed font
is needed in the control.
S select entire field when navigating to new field
...so replacing it's current value is done at first key pressed.

g) Other format codes:
0 integer fields get leading zeros
D Date[/time] field
T Time field
V validate entered chars against validRegex before allowing them to
be entered
, Allow grouping character in integer fields of numeric controls
- Reserved two space for negative number

IMHO, this control should not be used for generic numbers. The value
mostly is not a number,
but a IP, a date, a telephone number, etc. For numbers, there are
wxNumberValidators.
So, '0' ',' and '-' should not be here. Nor decimal separator, group
character, padding, etc.

h) I like the idea of allowing the user to set some validator[s]
function[s] on [each] field.
Same as now we can attach a validator to a wxTextCtrl, but for a field.

i) Allow/Exclude some characters. Allow/Exclude some strings. Both
options defined for each field.
With "allow" I really mean "list of only allowed".

j) Do a numeric range check. This is useful for example in a IP field,
checking 0-255 range values.
And also for a hour-field (0-24), a minute field (0-59), a so on.
Setting a range option, makes 'T' format code useless.
A combination of range and only-allowed strings makes possible to mask
a date such as 15-Oct-2012,
with three fields: first and third ranged, second field only allowed
(Jan, Feb, etc.). This way,
'D' format code would disappear.

k) Allow or not and empty field.

l) Replace and empty field with some default.

m) Autocomplete. Automatically or with some key (pagedown?). This
should be combined with allowed
strings.

n) Colors. Both background and foreground. In which situations?
- Invalid input
- valid, although incomplete
- Valid
- Default colors when nothing is yet typed, although some value is still there.
Colouring should be done when the field "loses focus", not only when
the control loses focus.

o) What about retaining focus when, after and invalid paste, some
field is invalid?.

p) When should "validation" be done? While typing allows char
filtering, but not range check.

q) Navigation. I suppose the idea is that the cursor "jumps" over the
separator to the next field
when the previous field has been full typed. In a IP field, after
typing the third digit, and range
check validates its value, the cursor goes on the next field.
But, what should TAB do? next field or next control?
Should cursor-keys allow jumping between fields or just inside one?
Typing the field separator, should be understood as "jump to next field"?
What other navigations keys (home, end, ctrl-up, etc) should do?


Most of these features are available (and a bit discussed in docs) in
my wxFormatValidator 2.0
(you can find it at wxCode).
So it will not be very difficult for me to implement them in wxMaskedEditCtrl.

There are three ways:
- Working with existing wxMaskedEditCtrl C++ code
- Translating most from current wxPython masked module to C++
- Restart from scratch

Most of the rules can be done with wxRegEx. So, perhaps it's just a
matter of avoid mask characters and format codes
and add just features like range check and colouring. I don't know.

Finally, the more I think of it, the more it fits in a validator, not
in a control.

What do you think?

Regards,
Manolo

Vadim Zeitlin

unread,
May 25, 2012, 7:33:35 AM5/25/12
to wx-...@googlegroups.com
On Fri, 25 May 2012 01:59:53 +0200 Manolo wrote:

M> I'm thinking of giving wxMaskedEditCtrl a try.

This would be most welcome, it's really a pity to still not have such a
useful control.

M> I found:
M> http://svn.wxwidgets.org/viewvc/wx/wxWidgets/branches/SOC2010_MASKED_CTRL/interface/wx/maskededit.h
M> and
M> http://wxpython.org/docs/api/wx.lib.masked.maskededit-module.html
M>
M> After reading those docs, I still have some thoughts and doubts:
M>
M> a) This is not a composite control, just an "edit control" which
M> allows only some kind of inputs.

It was meant to be used as a "decorator" for any text control. I.e. it
would modify the behaviour of an existing control.

M> Something similar to a wxValidator. Or, should it really be a
M> specialized validator?

I don't think it makes sense to make it a validator, it's too different
from the other ones. It also modifies the control appearance which is
something that normal validators never do. It is conceptually similar to
them though.

M> b) It shall work with wxTextCtrl and wxComboBox. I guess, with wxTextEntry.

Yes, and this is why it's a decorator instead of being a control itself.

M> c) The whole string at the control is divided into one or more
M> "fields", with something to
M> separate them. This "something separator" is given in the mask.
M> Example 1: "123.123.123.123" the separator is "."
M> Example 2: "12-mar-2012" the separator is "-"
M> Example 3: "04/10 23:15" with three separators "/", " " and ":"
M> Example 4: "(090)123123" with a prefix "(" and a separator ")"

Yes.

M> d) Mask characters, or "what this control is said to do"
M> # Allow numeric only (0-9)
M> N Allow letters and numbers (0-9)
M> A Allow uppercase letters only
M> a Allow lowercase letters only
M> C Allow any letter, upper or lower
M> It should be advised that uppercase/lowercase works well currently
M> just with latin characters.
M> X Allow string.letters, string.punctuation, string.digits
M> & Allow string.punctuation only (doesn't include all unicode symbols)
M> * Allow any visible character
M> What's intended with "punctuation"? Any other character like @#'<;?

% python -c 'import string; print string.punctuation'
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

M> What is a "visible" character?

My guess would be any character for which isprint() returns true.

M> | Field boundary. Fields are continuous, without separator between them
M> Is this "|" mandatory?

I don't really know.

M> All these "allow" characters mean you can type it, or not. But it lacks
M> a "you must" type it. If I need a four, not other than four, characters
M> field, how is this told in the mask?

I think all characters are required in this control (please consider
checking it with wxPython demo). I.e. if you have "####" mask then you need
to enter 4 digits for IsValid() to return true.

M> e) Literal characters may be set. So, with a mask like "##\a#.###"
M> valid inputs are "12a3.456"
M> or "45a1.900". How many fields are here? two: "12a3" and "456" or
M> three: "12" "a3" and "456"
M> And, if that "." is considered as a field separator, shouldn't that
M> "\a" be a field separator too?

I think it should be, yes. Any non-special character or any special
character escaped by a backslash should be treated the same.

M> Literals, must the user type them?

No.

M> f) Format codes:
M> _ Allow spaces
M> ! Force upper
M> ^ Force lower
M> R Right-align field(s)
M> r Right-insert in field(s) (implies R)
M> < Stay in field until explicit navigation out of it
M> I don't understand this "<"

Me neither. "!" and "^" are weird, for me "^" clearly evokes "force
upper". In any case, none of them is really absolutely needed and it would
be perfectly acceptable to have a first, simple version of the control
without them. In fact I think it would be preferable to have an as simple
as possible first version to make it easier to test it under all platforms
and ensure that at least the basic functionality does work everywhere.

M> > insert/delete/backspace behaviour.
M> As I understand this, delete/backspace-key can delete a char or the
M> whole field.

Probably, don't know. Not indispensable in the first version neither.

M> F Auto-Fit: The control calculate its size from the mask length.
M> What is this needed for? wxWindow::SetMinSize()?

Yes, probably.


M> h) I like the idea of allowing the user to set some validator[s]
M> function[s] on [each] field.

It's interesting but, again, it almost certainly shouldn't be in the first
version.

M> i) Allow/Exclude some characters. Allow/Exclude some strings. Both
M> options defined for each field.
M> With "allow" I really mean "list of only allowed".

I think this would be done with custom validators. We really can't
implement all kinds of possible checks in this class itself, so we should
only implement the most common ones and -- perhaps later -- make it
possible to define custom checks.

M> j) Do a numeric range check.

Same as (i).

M> k) Allow or not and empty field.

I don't think it matters if the field is empty or not. If we want to allow
leaving something empty we must use some indicator for this in the mask.
E.g. if "##" means "2 digits" then we could have "##?" for "1 or 2 digits".

M> l) Replace and empty field with some default.

I really don't think this belongs to this class. It's totally
application-specific.

M> m) Autocomplete. Automatically or with some key (pagedown?). This
M> should be combined with allowed strings.

Nice but let's leave it for later.

M> n) Colors. Both background and foreground.

This OTOH is specific enough to be implemented in the control itself.

M> - Invalid input
M> - valid, although incomplete
M> - Valid
M> - Default colors when nothing is yet typed, although some value is still there.

If you work on this, please define a struct/class containing all these
colours instead of adding separate functions for setting each of them.

M> o) What about retaining focus when, after and invalid paste, some
M> field is invalid?.

Sorry, what about it?

M> p) When should "validation" be done? While typing allows char
M> filtering, but not range check.

I think wxIntegerValidator experiment has successfully shown that
validation during typing is a bad idea. We could set the colours when the
field loses focus but there should be no error messages from the control at
all, leave it to the application code to do it when it wants.

M> q) Navigation. I suppose the idea is that the cursor "jumps" over the
M> separator to the next field when the previous field has been full typed.
M> In a IP field, after typing the third digit, and range
M> check validates its value, the cursor goes on the next field.

Yes, and this is pretty critical for the control usability.

M> But, what should TAB do? next field or next control?

Next field I'd say.

M> Should cursor-keys allow jumping between fields or just inside one?
M> Typing the field separator, should be understood as "jump to next field"?
M> What other navigations keys (home, end, ctrl-up, etc) should do?

I think we shouldn't do anything special (i.e. cursor keys should behave
by default, except that they should skip over fixed characters; typing a
separator should do nothing) at least initially.

M> There are three ways:
M> - Working with existing wxMaskedEditCtrl C++ code
M> - Translating most from current wxPython masked module to C++
M> - Restart from scratch
M>
M> Most of the rules can be done with wxRegEx.

I'm not sure if it's a good idea to use wxRegEx here.

M> Finally, the more I think of it, the more it fits in a validator, not
M> in a control.
M>
M> What do you think?

I don't believe this should be a validator. OTOH more I think about it,
more I become sure that we actually can't implement it as a pure decorator
neither because wxMaskedEditCtrl needs to override some methods. E.g. with
"####-##-##" mask you'd probably expect SetValue("20120525") to show
"2012-05-25" in the text control but how would you make this work without
overriding SetValue()? Well, maybe this is not such a problem if we had
wxMaskedEditCtrl::SetPlainValue() (there is already a GetPlainValue()).
Anyhow, if we can implement it as a decorator -- all the best. If not, the
least bad solution is to have a template wxMaskedEdit<T> class inheriting
from T, so that we could have wxMaskedEdit<wxTextCtrl> or
wxMaskedEdit<wxComboBox> or whatever.

As for the best approach, I think it would be nice to salvage something
from the existing wxMaskedEditCtrl code. However I don't think you can
really reuse much of it without any changes. So I guess I'd recommend
starting from scratch but reusing as much of it as possible.

In any case -- and I really can't emphasize this enough -- it would be an
excellent idea to have a version with as few features as possible but
working well under all platforms first. This would allow us to add it to
wxWidgets and we could proceed to extend it later. If you try to implement
all of the features listed above, it's going to take you years and you'll
probably never finish it and we won't have anything at all in wxWidgets any
time soon so this is definitely a case of "less is more".

Good luck,
VZ

Werner

unread,
May 26, 2012, 6:49:12 AM5/26/12
to wx-...@googlegroups.com
Hi Manolo,

On 25/05/2012 13:33, Vadim Zeitlin wrote:
> On Fri, 25 May 2012 01:59:53 +0200 Manolo wrote:
>
> M> I'm thinking of giving wxMaskedEditCtrl a try.
>
> This would be most welcome, it's really a pity to still not have such a
> useful control.
+1, I am using the wxPython version of these controls for a long time
and helped Will Sadkin in the testing of it.

> M> d) Mask characters, or "what this control is said to do"
> M> # Allow numeric only (0-9)
> M> N Allow letters and numbers (0-9)
> M> A Allow uppercase letters only
> M> a Allow lowercase letters only
> M> C Allow any letter, upper or lower
> M> It should be advised that uppercase/lowercase works well currently
> M> just with latin characters.
> M> X Allow string.letters, string.punctuation, string.digits
> M> & Allow string.punctuation only (doesn't include all unicode symbols)
> M> * Allow any visible character
> M> What's intended with "punctuation"? Any other character like @#'<;?
>
> % python -c 'import string; print string.punctuation'
> !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
>
> M> What is a "visible" character?
That was basically added to allow display of "Unicode" characters, to
deal with all the accents, and special characters like for Russian etc etc.

....
> M> All these "allow" characters mean you can type it, or not. But it lacks
> M> a "you must" type it. If I need a four, not other than four, characters
> M> field, how is this told in the mask?
>
> I think all characters are required in this control (please consider
> checking it with wxPython demo). I.e. if you have "####" mask then you need
> to enter 4 digits for IsValid() to return true.
Not in the wxPython version, i.e. it means you can enter up to 4 digits,
but 1, 2 and 3 digits are valid too.

...
> M> F Auto-Fit: The control calculate its size from the mask length.
> M> What is this needed for? wxWindow::SetMinSize()?
>
> Yes, probably.
BTW, the current calculation of the size is way overestimating what is
normally needed. A little while ago I suggested a patch to make the
sizing better (i.e. allocate less space to the control).

The current calculation uses "M" as the character to calculate the size,
in my suggested patch I use "9" for numctrl and a string of 10 different
characters for non numctrl's.

The suggested change for _calcsize is this:
# sizing of numctrl when using proportional font and
# wxPython 2.9 is not working when using "M"
# GetTextExtent returns a width which is way to large
# instead we use '9' for numctrl and a selection of
# characters instead of just 'M' for textctrl and combobox
# where the mask is larger then 10 characters long
if isinstance(self, wx.lib.masked.numctrl.NumCtrl):
sizing_text = '9' * self._masklength
wAdjust = 8
elif isinstance(self, wx.lib.masked.combobox.ComboBox):
if self._masklength > 10:
sizing_text = 'FDSJKLREUI' * (self._masklength/10)
wAdjust = 26
else:
sizing_text = 'M' * self._masklength
wAdjust = 4
else:
if self._masklength > 10:
sizing_text = 'FDSJKLREUI' * (self._masklength/10)
else:
sizing_text = 'M' * self._masklength
wAdjust = 4
if wx.Platform != "__WXMSW__": # give it a little extra space
sizing_text += 'M'
if wx.Platform == "__WXMAC__": # give it even a little
more...
sizing_text += 'M'
#### dbg('len(sizing_text):', len(sizing_text), 'sizing_text:
"%s"' % sizing_text)
w, h = self.GetTextExtent(sizing_text)
size = (w+wAdjust, self.GetSize().height)

This could probably be improved, but so far works for me in my tests.

Hope above is helpful and doesn't just add more confusion.

Werner

Manolo

unread,
May 28, 2012, 9:04:33 AM5/28/12
to wx-...@googlegroups.com
Hi
>  I don't think it makes sense to make it a validator, it's too different
> from the other ones. It also modifies the control appearance which is
> something that normal validators never do. It is conceptually similar to
> them though.
>
I don't get your concept of "validator". Perhaps you are thinking in
something that makes the control to have in every instant a valid
input.
But this can't be achieved for all cases. Those fields who have range
checkers (as hour, minute, etc) must allow the user to type the whole
field, even if is invalid while he types it.
My concept of validator is something that helps the user. Not just a
matter of filtering chars. Complex effects, like formatting or
colouring, are part of the validator tasks.

> M> b) It shall work with wxTextCtrl and wxComboBox. I guess, with wxTextEntry.
>
>  Yes, and this is why it's a decorator instead of being a control itself.
Are you talking about this:
wxTextCtrl aTextCtrl( .... );
wxMaskedDecorator MyDecorator(...., aTextCtrl);
If so, how some events will be handled by wxMaskedDecorator ?
The other way is something roughly like
class wxMaskedDecorator : public wxTextCtrl
or using templates.

> M> All these "allow" characters mean you can type it, or not. But it lacks
> M> a "you must" type it. If I need a four, not other than four, characters
> M> field, how is this told in the mask?
>
>  I think all characters are required in this control (please consider
> checking it with wxPython demo). I.e. if you have "####" mask then you need
> to enter 4 digits for IsValid() to return true.

I have figured out a way of having both options. "#|#|#|#" have 4
fields. We can set flags for each field telling if it can or can't
have am empty value.

> M>   F  Auto-Fit: The control calculate its size from the mask length.
> M> What is this needed for? wxWindow::SetMinSize()?
>
>  Yes, probably.
After reading the post from Werner, I can't get a good approach for
telling the width of the control. IMO, it's better a enough wider for
a "W"-chars input, even it implies too much space.

> M> o) What about retaining focus when, after and invalid paste, some
> M> field is invalid?.
>
>  Sorry, what about it?
Forget it. OTOH, a flag ("format code") can be set to tell if the
cursor will automatically jump to next field, or if it will be
"retained" in current field until a valid input is done.

>
> M> p) When should "validation" be done? While typing allows char
> M> filtering, but not range check.
>
>  I think wxIntegerValidator experiment has successfully shown that
> validation during typing is a bad idea. We could set the colours when the
> field loses focus but there should be no error messages from the control at
> all, leave it to the application code to do it when it wants.
I like wxPython behaviour. It allows wrong values. It does validation
for each char typed, and colors the control accordingly.

> M> But, what should TAB do? next field or next control?
>
>  Next field I'd say.
And when we are at the last field and receive TAB event, Skip() the
event, so focus can go to next control.

>  I think we shouldn't do anything special (i.e. cursor keys should behave
> by default, except that they should skip over fixed characters; typing a
> separator should do nothing) at least initially.
I agree.

>  I don't believe this should be a validator. OTOH more I think about it,
> more I become sure that we actually can't implement it as a pure decorator
> neither because wxMaskedEditCtrl needs to override some methods. E.g. with
> "####-##-##" mask you'd probably expect SetValue("20120525") to show
> "2012-05-25" in the text control but how would you make this work without
> overriding SetValue()? Well, maybe this is not such a problem if we had
> wxMaskedEditCtrl::SetPlainValue() (there is already a GetPlainValue()).
If all cells are filled (e.g. "125.147.001.241") a plain value is
clear: "125147001241". But "10.1.1.190" becomes what? "1011190" or "
10 1 1190".
IMO, GetValue() SetValue() will do just as they currently do, which
means they get/set a decorated value.
If you think it, a mask has its length fixed. So, get/set plain text
will operate with the fields, without decorations, leaving empty cells
with blank.
So, GetPlainText() will return " 10 1 1190". Or, if we have set the
'fillChar' to '?' then will return "?10??1??1190"

Other approach is to get field texts separated in a wxArrayString.

>  In any case -- and I really can't emphasize this enough -- it would be an
> excellent idea to have a version with as few features as possible but
> working well under all platforms first. This would allow us to add it to
> wxWidgets and we could proceed to extend it later. If you try to implement
> all of the features listed above, it's going to take you years and you'll
> probably never finish it and we won't have anything at all in wxWidgets
I have already started. I think "weeks" instead of "years", with
mostly all features implemented.

In order to use this control/decorator/validator in a validated
dialog, we need a specialized validator, with it's own Validate() and
Transfer() methods.

And, for using it in a grid, specialized GridEditors

Regards,
Manolo

Vadim Zeitlin

unread,
May 28, 2012, 9:14:20 AM5/28/12
to wx-...@googlegroups.com
On Mon, 28 May 2012 15:04:33 +0200 Manolo wrote:

M> I don't get your concept of "validator". Perhaps you are thinking in
M> something that makes the control to have in every instant a valid
M> input.

No, not at all. I'm thinking of validator as something that is relatively
decoupled from the control, in particular doesn't change how its methods
such as GetValue() and SetValue() behave.

M> My concept of validator is something that helps the user. Not just a
M> matter of filtering chars. Complex effects, like formatting or
M> colouring, are part of the validator tasks.

No, definitely not. If you look at wxValidator base class, there is
absolutely nothing about formatting here. Now if you want to completely
change this, we could discuss it, but this needs to be done for all
validators (thus changing the concept of "validator"), not for just one of
them.

M> > M> b) It shall work with wxTextCtrl and wxComboBox. I guess, with wxTextEntry.
M> >
M> >  Yes, and this is why it's a decorator instead of being a control itself.
M> Are you talking about this:
M> wxTextCtrl aTextCtrl( .... );
M> wxMaskedDecorator MyDecorator(...., aTextCtrl);
M> If so, how some events will be handled by wxMaskedDecorator ?

Handling events is not a problem at all, you can use Connect() for this
without problem. The trouble is with overriding virtual functions such as
SetValue(). But perhaps we don't need to do it. I'm still not sure about
this...

M> The other way is something roughly like
M> class wxMaskedDecorator : public wxTextCtrl
M> or using templates.

Yes, you could have

template <class T>
class wxMaskedEdit : public T { ... };

You could then instantiate it with T=wxTextCtrl or wxComboBox, for example.


M> > M> All these "allow" characters mean you can type it, or not. But it lacks
M> > M> a "you must" type it. If I need a four, not other than four, characters
M> > M> field, how is this told in the mask?
M> >
M> >  I think all characters are required in this control (please consider
M> > checking it with wxPython demo). I.e. if you have "####" mask then you need
M> > to enter 4 digits for IsValid() to return true.
M>
M> I have figured out a way of having both options. "#|#|#|#" have 4
M> fields. We can set flags for each field telling if it can or can't
M> have am empty value.

This is ugly though. I'm for breaking compatibility with Python version
here and just making "####" mean 4 characters.


M> If all cells are filled (e.g. "125.147.001.241") a plain value is
M> clear: "125147001241". But "10.1.1.190" becomes what? "1011190" or "
M> 10 1 1190".

For this one GetPlainText() doesn't make much sense anyhow. It's more
appropriate for e.g. phone numbers with "(###)-### ## ##" mask. In this
case it makes sense to exclude "()" and "-" from the value.

M> IMO, GetValue() SetValue() will do just as they currently do, which
M> means they get/set a decorated value.

This is surely the simplest approach and there is something (a lot,
actually) to be said for it. Let's so it like this.

M> So, GetPlainText() will return " 10 1 1190". Or, if we have set the
M> 'fillChar' to '?' then will return "?10??1??1190"

I don't think we need "fillChar". If you need something like this you can
just use GetValue().

M> Other approach is to get field texts separated in a wxArrayString.

It would perhaps be better to have GetFieldValue(index).


M> >  In any case -- and I really can't emphasize this enough -- it would be an
M> > excellent idea to have a version with as few features as possible but
M> > working well under all platforms first. This would allow us to add it to
M> > wxWidgets and we could proceed to extend it later. If you try to implement
M> > all of the features listed above, it's going to take you years and you'll
M> > probably never finish it and we won't have anything at all in wxWidgets
M> I have already started. I think "weeks" instead of "years", with
M> mostly all features implemented.

It might be already too late but even if you are absolutely sure that you
can do it in weeks, please consider starting with maximally simplified
version. This will give us a fighting chance to integrate it into wx soon,
maybe even before 2.9.4 (which will clearly be delayed as I haven't heard
anything about AUI changes yet and we're already at the end of May...). If
you try to push all the changes at once, it will be extremely difficult to
apply them. Please start with the smallest possible patch with the very
basic functionality and let's add more features later.

M> In order to use this control/decorator/validator in a validated dialog,
M> we need a specialized validator, with it's own Validate() and Transfer()
M> methods.

Yes.

M> And, for using it in a grid, specialized GridEditors

Yes.

But both can be done later, as separate patches.

TIA,
VZ

Werner

unread,
May 28, 2012, 11:06:57 AM5/28/12
to wx-...@googlegroups.com
On 28/05/2012 15:14, Vadim Zeitlin wrote:
> On Mon, 28 May 2012 15:04:33 +0200 Manolo wrote:
...
> M> > M> All these "allow" characters mean you can type it, or not. But it lacks
> M> > M> a "you must" type it. If I need a four, not other than four, characters
> M> > M> field, how is this told in the mask?
> M> >
> M> > I think all characters are required in this control (please consider
> M> > checking it with wxPython demo). I.e. if you have "####" mask then you need
> M> > to enter 4 digits for IsValid() to return true.
> M>
> M> I have figured out a way of having both options. "#|#|#|#" have 4
> M> fields. We can set flags for each field telling if it can or can't
> M> have am empty value.
>
> This is ugly though.
+1
> I'm for breaking compatibility with Python version
> here and just making "####" mean 4 characters.
-1, what about having a switch/flag to state if has to be zero filled or
"#" means numeric has to have a value and have some other other char to
define it as can be blank.

But on the other hand "N", "A", "a", "C", "X" and "*" all just define
what is allowed in the particular position of the mask and that normally
includes " " (blank), so "#" should be consistent with e.g. "A".

Werner

Vadim Zeitlin

unread,
May 28, 2012, 11:14:21 AM5/28/12
to wx-...@googlegroups.com
On Mon, 28 May 2012 17:06:57 +0200 Werner wrote:

W> > I'm for breaking compatibility with Python version
W> > here and just making "####" mean 4 characters.
W> -1, what about having a switch/flag to state if has to be zero filled or
W> "#" means numeric has to have a value and have some other other char to
W> define it as can be blank.

I'm fine with having some way to indicate that a character (be it digit,
letter or anything else) is optional. But I still think that it should be
required by default as most of the examples of use of this control I can
think of are for fixed width data entry.

W> But on the other hand "N", "A", "a", "C", "X" and "*" all just define
W> what is allowed in the particular position of the mask and that normally
W> includes " " (blank), so "#" should be consistent with e.g. "A".

Does "A" really include " "? This seems wrong to me, a letter is a letter
and not "a letter or a space". Also notice that entering space is not the
same as not entering anything at all.

Regards,
VZ

Manolo

unread,
May 28, 2012, 11:42:22 AM5/28/12
to wx-...@googlegroups.com
>  No, definitely not. If you look at wxValidator base class, there is
> absolutely nothing about formatting here. Now if you want to completely
> change this, we could discuss it, but this needs to be done for all
> validators (thus changing the concept of "validator"), not for just one of
> them.
Sorry. wxIntegerValidator _does_ formatting.

> M> Are you talking about this:
> M>     wxTextCtrl aTextCtrl( .... );
> M>     wxMaskedDecorator MyDecorator(...., aTextCtrl);
> M> If so, how some events will be handled by wxMaskedDecorator ?
>
>  Handling events is not a problem at all, you can use Connect() for this
> without problem. The trouble is with overriding virtual functions such as
> SetValue(). But perhaps we don't need to do it. I'm still not sure about
> this...
Yes. Connect() is what I used for my GridEditors in my wxFormatValidator.
Handling wxEVT_COMMAND_TEXT_UPDATED event would avoid SetValue() overriding.

> M> I have figured out a way of having both options. "#|#|#|#" have 4
> M> fields. We can set flags for each field telling if it can or can't
> M> have am empty value.
>
>  This is ugly though. I'm for breaking compatibility with Python version
> here and just making "####" mean 4 characters.
I said _both_ options. "####" would mean "always 4 characters".
"#|#|#|#" is more configurable.
It can be like "(###)#|#|#" (4 fields) where inside () can be blank
and the rest may be not, depending on the flags for each field.

I'm organizing three levels of validation:
- cell (one char) level. '#' is checked to be a digit. 'a' is checked
to be a lower case letter (with wxIslower()), an so on
- field level. "##" can be told to be a 'hour' field. So each cell
must be a digit (cell level) and also the whole field must be in
[0-23] range.
- control level. A date can be written in several ways (e.g.
"2012-05-28" "2012-May-28" "28/05/2012"). We can have a dedicated
function
bool CheckDate(size_t yearField, size_t monthField, size_t dayField)
that test the date to be valid even for leap years.

Cell validation is always configured with the mask commands (#, N, a, etc)
Field validation will also be configured with special mask commands (D
for day, M for month, m for letter-month, Y for year). And can be also
told to use an external, user defined, function.
Control level may be configured like field level, with some predefined
functions or with external ones.

> M> IMO, GetValue() SetValue() will do just as they currently do, which
> M> means they get/set a decorated value.
>
>  This is surely the simplest approach and there is something (a lot,
> actually) to be said for it. Let's so it like this.
So:
GetValue() SetValue() remain unmodified. They work with whole
control's value, decorations included.
Get/Set PlainValue() just take decorations out.
Get/Set FieldValue(index) for the part inside the field.
The above get() functions return a wxString.

> M> So, GetPlainText() will return " 10  1  1190". Or, if we have set the
> M> 'fillChar' to '?' then will return "?10??1??1190"
>
>  I don't think we need "fillChar". If you need something like this you can
> just use GetValue().
'?' is not a literal (read, a decoration). It is inside the field. It
may be useful when the mask allows blanks which may be different from
"not typed yet this character"

>  It might be already too late but even if you are absolutely sure that you
> can do it in weeks, please consider starting with maximally simplified
> version. This will give us a fighting chance to integrate it into wx soon,
OK. I'll try just "commands" in mask. No complex flags (i.e. align,
cursor retain, etc). Perhaps some predefined function.

Would be this part of core/base/adv...?
WXDLLIMPEXP_CORE macro?

Regards
Manolo

Werner

unread,
May 28, 2012, 11:59:41 AM5/28/12
to wx-...@googlegroups.com
Hi,

On 28/05/2012 15:04, Manolo wrote:
...
>> M> F Auto-Fit: The control calculate its size from the mask length.
>> M> What is this needed for? wxWindow::SetMinSize()?
>>
>> Yes, probably.
> After reading the post from Werner, I can't get a good approach for
> telling the width of the control. IMO, it's better a enough wider for
> a "W"-chars input, even it implies too much space.
Using "W" or "M" is the save bet, but it really means pretty ugly UI's,
i.e. way to wide and sometimes one can then only have 1 or 2 columns of
controls instead of 3 or 4.....

Any chance of having a way to easily override how space is calculated?

Werner

Werner

unread,
May 28, 2012, 12:02:26 PM5/28/12
to wx-...@googlegroups.com
On 28/05/2012 17:14, Vadim Zeitlin wrote:
> On Mon, 28 May 2012 17:06:57 +0200 Werner wrote:
>
> W> > I'm for breaking compatibility with Python version
> W> > here and just making "####" mean 4 characters.
> W> -1, what about having a switch/flag to state if has to be zero filled or
> W> "#" means numeric has to have a value and have some other other char to
> W> define it as can be blank.
>
> I'm fine with having some way to indicate that a character (be it digit,
> letter or anything else) is optional. But I still think that it should be
> required by default as most of the examples of use of this control I can
> think of are for fixed width data entry.
>
> W> But on the other hand "N", "A", "a", "C", "X" and "*" all just define
> W> what is allowed in the particular position of the mask and that normally
> W> includes " " (blank), so "#" should be consistent with e.g. "A".
>
> Does "A" really include " "?
Sorry, for misleading, you are right "A" is only letters, being able to
have trailing "blanks" is set with format code "_ Allow spaces".

Werner

Manolo

unread,
May 28, 2012, 12:08:49 PM5/28/12
to wx-...@googlegroups.com
> Sorry, for misleading, you are right "A" is only letters, being able to have
> trailing "blanks" is set with format code "_  Allow spaces".
The format codes (I prefer 'flags') "allow spaces" is not the same as
"allow empty, not typed, character"

Manolo

unread,
May 28, 2012, 12:13:26 PM5/28/12
to wx-...@googlegroups.com
> Using "W" or "M" is the save bet, but it really means pretty ugly UI's, i.e.
> way to wide and sometimes one can then only have 1 or 2 columns of controls
> instead of 3 or 4.....
>
> Any chance of having a way to easily override how space is calculated?
With fixed size fonts there's not problem at all.
With other fonts, every size calculation, is a "possible size".
Changing control's size (with the exact one) each time a character is
written is a really bad option.

Vadim Zeitlin

unread,
May 28, 2012, 12:51:10 PM5/28/12
to wx-...@googlegroups.com
On Mon, 28 May 2012 17:42:22 +0200 Manolo wrote:

M> >  No, definitely not. If you look at wxValidator base class, there is
M> > absolutely nothing about formatting here. Now if you want to completely
M> > change this, we could discuss it, but this needs to be done for all
M> > validators (thus changing the concept of "validator"), not for just one of
M> > them.
M> Sorry. wxIntegerValidator does formatting.

Which is probably a bad idea as well... But it's still much more limited
than what you have in mind.

M> > M> Are you talking about this:
M> > M>     wxTextCtrl aTextCtrl( .... );
M> > M>     wxMaskedDecorator MyDecorator(...., aTextCtrl);
M> > M> If so, how some events will be handled by wxMaskedDecorator ?
M> >
M> >  Handling events is not a problem at all, you can use Connect() for this
M> > without problem. The trouble is with overriding virtual functions such as
M> > SetValue(). But perhaps we don't need to do it. I'm still not sure about
M> > this...
M> Yes. Connect() is what I used for my GridEditors in my wxFormatValidator.
M> Handling wxEVT_COMMAND_TEXT_UPDATED event would avoid SetValue() overriding..

Not really, there is also ChangeValue() and GetValue(). You can't do
everything with the events.

M> > M> I have figured out a way of having both options. "#|#|#|#" have 4
M> > M> fields. We can set flags for each field telling if it can or can't
M> > M> have am empty value.
M> >
M> >  This is ugly though. I'm for breaking compatibility with Python version
M> > here and just making "####" mean 4 characters.
M> I said both options. "####" would mean "always 4 characters".
M> "#|#|#|#" is more configurable.
M> It can be like "(###)#|#|#" (4 fields) where inside () can be blank
M> and the rest may be not, depending on the flags for each field.

That's fine but why "|" for "optional"? I thought about "?" (obvious) or
"*" (regex) or "[x]" (BNF grammar) but "|" is something I have real trouble
understanding. Where does this come from?

M> I'm organizing three levels of validation:
M> - cell (one char) level. '#' is checked to be a digit. 'a' is checked
M> to be a lower case letter (with wxIslower()), an so on
M> - field level. "##" can be told to be a 'hour' field. So each cell
M> must be a digit (cell level) and also the whole field must be in
M> [0-23] range.
M> - control level. A date can be written in several ways (e.g.
M> "2012-05-28" "2012-May-28" "28/05/2012"). We can have a dedicated
M> function bool CheckDate(size_t yearField, size_t monthField, size_t
M> dayField) that test the date to be valid even for leap years.
M>
M> Cell validation is always configured with the mask commands (#, N, a, etc)

Yes.

M> Field validation will also be configured with special mask commands

I'd really rather avoid it in the first version. I am not sure at all it's
a good idea, IMO it would be better to provide an extensive user-defined
mechanism for field validation. Unfortunately I simply don't have
time/energy to think/discuss this now. Can we postpone it?

M> Get/Set PlainValue() just take decorations out.
M> Get/Set FieldValue(index) for the part inside the field.
M> The above get() functions return a wxString.

Yes, sounds good.

M> > M> So, GetPlainText() will return " 10  1  1190". Or, if we have set the
M> > M> 'fillChar' to '?' then will return "?10??1??1190"
M> >
M> >  I don't think we need "fillChar". If you need something like this you can
M> > just use GetValue().
M> '?' is not a literal (read, a decoration). It is inside the field. It
M> may be useful when the mask allows blanks which may be different from
M> "not typed yet this character"

Again, what's the purpose of this? Remember that every method/parameter
you add must be documented and tested. Why add an apparently unnecessary
parameter when you already have GetFieldValue()?

M> Would be this part of core/base/adv...?
M> WXDLLIMPEXP_CORE macro?

I'd say "adv".

Thanks,
VZ

Manolo

unread,
May 28, 2012, 2:42:53 PM5/28/12
to wx-...@googlegroups.com
>  Not really, there is also ChangeValue() and GetValue(). You can't do
> everything with the events.
OK. I implement it with templates.

>  That's fine but why "|" for "optional"? I thought about "?" (obvious) or
> "*" (regex) or "[x]" (BNF grammar) but "|" is something I have real trouble
> understanding. Where does this come from?
For what I think, '|' is used to separate fields without any
decoration between them. While "#-A" shows like " - " (space, minus,
space) and accept "1-J", "#|A" may show like " " (2 spaces) and
accept "1J".

> M> Field validation will also be configured with special mask commands
>
>  I'd really rather avoid it in the first version. I am not sure at all it's
> a good idea, IMO it would be better to provide an extensive user-defined
> mechanism for field validation. Unfortunately I simply don't have
> time/energy to think/discuss this now. Can we postpone it?
I will (in later version) also provide user-defined field and control
validation.

> M> Get/Set PlainValue() just take decorations out.
> M> Get/Set FieldValue(index) for the part inside the field.
> M> The above get() functions return a wxString.
>
>  Yes, sounds good.
Done.

>
> M> > M> So, GetPlainText() will return " 10  1  1190". Or, if we have set the
> M> > M> 'fillChar' to '?' then will return "?10??1??1190"
> M> >
> M> >  I don't think we need "fillChar". If you need something like this you can
> M> > just use GetValue().
> M> '?' is not a literal (read, a decoration). It is inside the field. It
> M> may be useful when the mask allows blanks which may be different from
> M> "not typed yet this character"
>
>  Again, what's the purpose of this? Remember that every method/parameter
> you add must be documented and tested. Why add an apparently unnecessary
> parameter when you already have GetFieldValue()?
This is a way to tell between 'space' and 'not typed yet'.

Regards,
Manolo

Vadim Zeitlin

unread,
May 28, 2012, 3:02:06 PM5/28/12
to wx-...@googlegroups.com
On Mon, 28 May 2012 20:42:53 +0200 Manolo wrote:

M> >  Not really, there is also ChangeValue() and GetValue(). You can't do
M> > everything with the events.
M> OK. I implement it with templates.

Err, I thought we decided that we didn't need to override anything
finally? If we don't, then decorator approach (used in the GSoC branch
IIRC) is just fine.

M> >  That's fine but why "|" for "optional"? I thought about "?" (obvious) or
M> > "*" (regex) or "[x]" (BNF grammar) but "|" is something I have real trouble
M> > understanding. Where does this come from?
M> For what I think, '|' is used to separate fields without any
M> decoration between them.

I do accept "|" as a separator between the fields but this makes it even
more confusing. If I want to have a single logical field consisting of 2 or
3 letters and 2 digits I'd need to write it as "AAA|##" which makes it seem
like there are 2 fields which is wrong.

Also, what is the mask for 2-4 letters field with this approach? "AAA|A|"?
This just looks strange. IMHO "AAA?A?" is better and personally I'd really
rather write it as "A{2,4}" but I probably love regexes a bit too much.

Anyhow, I'd really prefer just about anything to "|". It seems very
unmnemonic and confusing to me.

M> >  Again, what's the purpose of this? Remember that every method/parameter
M> > you add must be documented and tested. Why add an apparently unnecessary
M> > parameter when you already have GetFieldValue()?
M> This is a way to tell between 'space' and 'not typed yet'.

Doesn't GetField() give you the same information? I.e. if you have a field
of 4 characters but GetField() returns a string of length 2, then you know
that only 2 were entered (whether they were space or not).

Regards,
VZ

Manolo

unread,
May 28, 2012, 4:28:13 PM5/28/12
to wx-...@googlegroups.com
> M> >  Not really, there is also ChangeValue() and GetValue(). You can't do
> M> > everything with the events.
> M> OK. I implement it with templates.
>
>  Err, I thought we decided that we didn't need to override anything
> finally? If we don't, then decorator approach (used in the GSoC branch
> IIRC) is just fine.
Excuse me, it's not clear for me.
GSoC branch modifies wxTextCtrl (and company) files. I don't like this.
I prefer wxMaskedEdit deriving from text/combo controls, as you suggested:
template <class T>
class wxMaskedEdit : public T { ... };
Overriding may still be needed. SetValue(val) should test 'val' (to
decide colors and perhaps replace literals) and then just call its
base T::SetValue(val). Same goes for ChangeValue().
All the rest are new functions in the new derived class. Action takes
place when SetPlainValue, SetFieldValue and key/char/paste events.

Am I wrong?

Manolo

Vadim Zeitlin

unread,
May 28, 2012, 5:37:38 PM5/28/12
to wx-...@googlegroups.com
On Mon, 28 May 2012 22:28:13 +0200 Manolo wrote:

M> > M> >  Not really, there is also ChangeValue() and GetValue(). You can't do
M> > M> > everything with the events.
M> > M> OK. I implement it with templates.
M> >
M> >  Err, I thought we decided that we didn't need to override anything
M> > finally? If we don't, then decorator approach (used in the GSoC branch
M> > IIRC) is just fine.
M> Excuse me, it's not clear for me.
M> GSoC branch modifies wxTextCtrl (and company) files. I don't like this.

Me neither, I'd prefer to not modify them but have wxMaskedEdit as a
completely separate class which could be associated -- as validators can --
with a control during run-time instead.

M> I prefer wxMaskedEdit deriving from text/combo controls, as you suggested:
M> template <class T>
M> class wxMaskedEdit : public T { ... };
M> Overriding may still be needed. SetValue(val) should test 'val' (to
M> decide colors and perhaps replace literals) and then just call its
M> base T::SetValue(val). Same goes for ChangeValue().
M> All the rest are new functions in the new derived class. Action takes
M> place when SetPlainValue, SetFieldValue and key/char/paste events.
M>
M> Am I wrong?

Well, again, if we do need to override any functions then it must be done
like this, yes. But I'd actually prefer to have a separate wxMaskedEdit
which could be just associated (possibly directly when constructed,
possibly later) with another wxTextEntry. This would be IMO more flexible,
so if we can do it like this, I'd prefer to.

Regards,
VZ

Manolo

unread,
May 28, 2012, 6:22:52 PM5/28/12
to wx-...@googlegroups.com
>  I do accept "|" as a separator between the fields but this makes it even
> more confusing. If I want to have a single logical field consisting of 2 or
> 3 letters and 2 digits I'd need to write it as "AAA|##" which makes it seem
> like there are 2 fields which is wrong.
Use '|' when you need fields validation.
"AAA##" is an only field, with cell (character) validation.
"AAA|##" or "AAA-##" have two fields, both with cell validation. And
you can add a [user] validation for first field and another different
validation for second field.
'|' is a separator needed when you don't want to see in the control
anything between fields, but still want to do per field validation.

>  Also, what is the mask for 2-4 letters field with this approach? "AAA|A|"?
> This just looks strange. IMHO "AAA?A?" is better and personally I'd really
> rather write it as "A{2,4}" but I probably love regexes a bit too much.
We, or the user, can use regexes in the [external] validation functions.

> M> > parameter when you already have GetFieldValue()?
> M> This is a way to tell between 'space' and 'not typed yet'.
>
>  Doesn't GetField() give you the same information? I.e. if you have a field
> of 4 characters but GetField() returns a string of length 2, then you know
> that only 2 were entered (whether they were space or not).
IMHO GetFieldValue() would return a string wtih a number of characters
identical to field's mask. And depending on align flags, leave blanks
in one side or another. Would this change the meaning of the field?
If the field is a number (like a minute 0-59), " 6", "6 " and "06"
are all the same and it's not important if spaces are there or not.
But I suppose it is possible a case where this cell position
information may be needed. By now, I can't imagine one. Let's postpone
it for a later version.

> Well, again, if we do need to override any functions then it must be done
> like this, yes. But I'd actually prefer to have a separate wxMaskedEdit
> which could be just associated (possibly directly when constructed,
> possibly later) with another wxTextEntry. This would be IMO more flexible,
> so if we can do it like this, I'd prefer to.
I agree. But I still think Set/ChangeValue have to be overriding.

Regards
Manolo

Vadim Zeitlin

unread,
May 29, 2012, 1:27:48 PM5/29/12
to wx-...@googlegroups.com
On Tue, 29 May 2012 00:22:52 +0200 Manolo wrote:

M> >  I do accept "|" as a separator between the fields but this makes it even
M> > more confusing. If I want to have a single logical field consisting of 2 or
M> > 3 letters and 2 digits I'd need to write it as "AAA|##" which makes it seem
M> > like there are 2 fields which is wrong.
M> Use '|' when you need fields validation.

So "|" is a field separator. Why is it reused to indicate whether a
character is optional or not?

I'm sorry but I find this very confusing and while I could, obviously, be
just missing something I believe it's not a good sign if the rules are so
difficult to explain as they risk to be confusing to wx users as well.
Could we please do something simpler, e.g.:

1. Use "?" or "{N,M}" notation for optional characters.
2. Use "|" for "invisible field separator" and nothing else.

?

M> >  Also, what is the mask for 2-4 letters field with this approach? "AAA|A|"?
M> > This just looks strange. IMHO "AAA?A?" is better and personally I'd really
M> > rather write it as "A{2,4}" but I probably love regexes a bit too much.
M> We, or the user, can use regexes in the [external] validation functions.

Yes, but I think it could be nice to be able to use this directly in the
mask too. I don't advocate using arbitrary regexes here, of course, but
this syntax seems to be relatively clear to me.

But again, I'm fine with "A?" or "A_" or whatever else too. I just don't
understand at all why should "|" be used for this.


M> IMHO GetFieldValue() would return a string wtih a number of characters
M> identical to field's mask.

Hmm, I didn't think about this. Is this really useful?

M> By now, I can't imagine one. Let's postpone it for a later version.

Agreed.

M> > Well, again, if we do need to override any functions then it must be done
M> > like this, yes. But I'd actually prefer to have a separate wxMaskedEdit
M> > which could be just associated (possibly directly when constructed,
M> > possibly later) with another wxTextEntry. This would be IMO more flexible,
M> > so if we can do it like this, I'd prefer to.
M> I agree. But I still think Set/ChangeValue have to be overriding.

If we start by having a pure decorator we can always trivially have the
template class inheriting from its template parameter later. And actually
it's the right way to do it anyhow to avoid template bloat: all
type-independent code would be in wxMaskEdit decorator and (template)
wxMaskEditCtrl would be fully inline and relatively trivial. So let's start
by adding wxMaskEdit and we'll see if we need wxMaskEditCtrl later.

Thanks,
VZ

Manolo

unread,
May 29, 2012, 2:58:20 PM5/29/12
to wx-...@googlegroups.com
>  So "|" is a field separator. Why is it reused to indicate whether a
> character is optional or not?
It is not reused.
> 2. Use "|" for "invisible field separator" and nothing else.
This is. You've got it. And thanks for that good definition.

> M> We, or the user, can use regexes in the [external] validation functions.
>
>  Yes, but I think it could be nice to be able to use this directly in the
> mask too. I don't advocate using arbitrary regexes here, of course, but
> this syntax seems to be relatively clear to me.
Do you mean overloading SetMask(wxString) with SetMask(wxRegex) ?
OK, but for later version.

>  If we start by having a pure decorator we can always trivially have the
> template class inheriting from its template parameter later. And actually
> it's the right way to do it anyhow to avoid template bloat: all
> type-independent code would be in wxMaskEdit decorator and (template)
> wxMaskEditCtrl would be fully inline and relatively trivial. So let's start
> by adding wxMaskEdit and we'll see if we need wxMaskEditCtrl later.
What I am currently doing is having a 'base' wxMaskEdit to do most of
task: set/get mask & parameters, filtering, validating, etc.
wxMaskEditCtrl will derive from this wxMaskEdit and also from the
desired wxTextCtrl, wxCombobox.
wxMaskEditCtrl is the bridge between the control 'on screen' and the
'worker behind'.
I near sure that we need this approach, not only for Set/Change
Value(), but also because of setting MinSize.

Regards
Manolo

Manolo

unread,
May 29, 2012, 3:36:19 PM5/29/12
to wx-...@googlegroups.com
More to think about:
How much "compatible" would this new wxMaskEdit be with current wxPython one?

I mean:
Do we keep 'format codes' like '_!^' ?
The allow spaces '_' could be defined per character and not for the
whole field or control. But this means duplicating the number of mask
commands.
And in the same way, '!' could be incorporated in a new command. But
again, that's bloating.

'^' may be inconsistent with the command 'A'. The first means "convert
this letter to lowercase" while 'A' means "accept only an uppercase
letter".

Looking (perhaps not enough deeply) inside wxPython code, when _OnChar
is called, I see this order:
1) First use [some of the] the format code (in our sample, '^')
2) If char is in the exclude-list, filter it and return.
3) If the char is in the allowed-list, accept it and return.
4) Check the char against the mask, return if failed
5) Other checks (regex, custom, etc)

I prefer the order: 3, 2, 4, 5, 1 or 3, 2, 4, 1, 5
So, we can throw away that inconsistency.
IMHO 3) has preference over 2)
The 5) step is, in wxMaskEdit, where the code calls the function
defined for field/control.
The user can replace the one predefined there with its own function.

Regards
Manolo

Vadim Zeitlin

unread,
May 29, 2012, 7:25:40 PM5/29/12
to wx-...@googlegroups.com
On Tue, 29 May 2012 20:58:20 +0200 Manolo wrote:

M> >  So "|" is a field separator. Why is it reused to indicate whether a
M> > character is optional or not?
M> It is not reused.
M> > 2. Use "|" for "invisible field separator" and nothing else.
M> This is. You've got it. And thanks for that good definition.

Ok. Now I don't understand how does it help with making any characters
optional. Could you please show how do you define masks for the entries
consisting of:

1. Exactly 5 digits.
2. From 3 to 5 digits.
3. Up to 50 letters.

?

M> > M> We, or the user, can use regexes in the [external] validation functions.
M> >
M> >  Yes, but I think it could be nice to be able to use this directly in the
M> > mask too. I don't advocate using arbitrary regexes here, of course, but
M> > this syntax seems to be relatively clear to me.
M> Do you mean overloading SetMask(wxString) with SetMask(wxRegex) ?

No, not at all. As I said, I do not advocate using arbitrary regexes, it
wouldn't be possible anyhow. I just wanted to use regex-like syntax for the
mask here, i.e. my syntax for the examples from the above would be:

1. #{5}
2. #{3,5}
3. A{,50}

M> What I am currently doing is having a 'base' wxMaskEdit to do most of
M> task: set/get mask & parameters, filtering, validating, etc.

OK, very good.

M> wxMaskEditCtrl will derive from this wxMaskEdit and also from the
M> desired wxTextCtrl, wxCombobox.

OK as long as this wxMaskEditCtrl is basically trivial and delegates all
the work to wxMaskEdit.

M> I near sure that we need this approach, not only for Set/Change
M> Value(), but also because of setting MinSize.

You can just call SetMinSize() from wxMaskEdit, can't you?


M> More to think about:
M> How much "compatible" would this new wxMaskEdit be with current wxPython one?

I don't think compatibility is that important. I don't see Python
programmers switching to C++ just because we now have wxMaskEdit in it...
And if we change all symbols to be required by default whereas in Python
they're optional IIUC, exact compatibility goes out of the window anyhow
and it's better to not even create the illusion that the API is compatible
then.

M> I mean:
M> Do we keep 'format codes' like '_!^' ?

Personally I find at least some of them very confusing.

M> '^' may be inconsistent with the command 'A'. The first means "convert
M> this letter to lowercase" while 'A' means "accept only an uppercase
M> letter".

I think "A" with this meaning is pretty useless. If you need uppercase
letters only, why wouldn't you allow the user to enter lowercase ones and
convert them automatically? This would be just petty.

M> Looking (perhaps not enough deeply) inside wxPython code, when _OnChar
M> is called, I see this order:
M> 1) First use [some of the] the format code (in our sample, '^')
M> 2) If char is in the exclude-list, filter it and return.
M> 3) If the char is in the allowed-list, accept it and return.
M> 4) Check the char against the mask, return if failed
M> 5) Other checks (regex, custom, etc)
M>
M> I prefer the order: 3, 2, 4, 5, 1 or 3, 2, 4, 1, 5
M> So, we can throw away that inconsistency.
M> IMHO 3) has preference over 2)

Why do we need accept and exclude lists at all? Aren't they redundant with
the mask?

M> The 5) step is, in wxMaskEdit, where the code calls the function
M> defined for field/control.
M> The user can replace the one predefined there with its own function.

I think in C++ it would be natural to have a virtual function to do the
check. Then you could override it and call the base class version either
before or after your own code (or not at all) so that you could choose any
order you want.

Regards,
VZ

Manolo

unread,
May 30, 2012, 7:32:22 AM5/30/12
to wx-...@googlegroups.com
>  Ok. Now I don't understand how does it help with making any characters
> optional. Could you please show how do you define masks for the entries
> consisting of:
>
> 1. Exactly 5 digits.
> 2. From 3 to 5 digits.
> 3. Up to 50 letters.
1. #{5} without the flag '_' (allow spaces)
2. ##|#|#|# '_' set for the first field, but not set for the other three
3. C{50} '_' is set

> 1. #{5}
> 2. #{3,5}
> 3. A{,50}
Shorter, yes. Regex may be more beautiful.

What about this?:
# a digit or nothing
0 a digit
H a hexadecimal digit
a any character (space is not), forced to lower
A any character (space is not), forced to upper
s any character (space allowed), forced to lower
S any character (space allowed), forced to lower
N any digit or character or space or nothing

Spaces are blurring me. Suppose for some reason we have in a IP fleld
the string "1 3". GetFieldValue() may join the digits, deleting that
space, to get "13". Now suppose we have a "first name" field. In
Spanish a compound name (i.e "Jose Antonio") is valid. So we can not
delete the space (but we can delete spaces at left & right).
I'm trying to tell how to treat these cases, either with the mask or
with some flag.
If a right-align flag is set for that "first name" field, typing the
space is impossible, because GetFielValue would always return "Jose"
because it deleted left-right spaces. So GetFieldValue would not
delete spaces, retuning always the whole field, filled or not. Which
makes it wrong with "1 3 "... Blurring. Yes.
> M> I near sure that we need this approach, not only for Set/Change
> M> Value(), but also because of setting MinSize.
>
>  You can just call SetMinSize() from wxMaskEdit, can't you?
Yes, of course.
Also, if the control derives from wxWindow, wxFrame can take ownership
of the pointer and delete it when the window is closed.

>  Why do we need accept and exclude lists at all? Aren't they redundant with
> the mask?
To allow a field which allows not only what is set from the mask, but
also other options. Example, a digit or one of "XM".
Other example: any char, except one of "abc"
Other more: a 3-digits number, or one of the words "min" "max"

>
> M> The 5) step is, in wxMaskEdit, where the code calls the function
> M> defined for field/control.
> M> The user can replace the one predefined there with its own function.
>
>  I think in C++ it would be natural to have a virtual function to do the
> check. Then you could override it and call the base class version either
> before or after your own code (or not at all) so that you could choose any
> order you want.
wxMaskEdit will have some predefined functions, as public members.
For example, DayCheck(...) returning false if not in the [1-31]
range. This function is automatically set as the "function for this
field" when something in the mask/flag tells so. SetFieldFunct().
In order the user can use his own function, he must call
SetFieldFunct() after he sets the mask, replacing the default func.
And here are two ways:
- We define SetFieldFunction(ExFun), where ExFun is a function that
has a wxMaskEdit * parameter.
- The user derives his own object from wxMaskText/Combo. He will need
to add his own members and set them with SetFieldFunction for
validation.
The idea is the user can get not only current field, but anything.
This way, he can validate field/control depending on other/all fields.

Regards
Manolo

Vadim Zeitlin

unread,
May 30, 2012, 4:02:52 PM5/30/12
to wx-...@googlegroups.com
On Wed, 30 May 2012 13:32:22 +0200 Manolo wrote:

M> >  Ok. Now I don't understand how does it help with making any characters
M> > optional. Could you please show how do you define masks for the entries
M> > consisting of:
M> >
M> > 1. Exactly 5 digits.
M> > 2. From 3 to 5 digits.
M> > 3. Up to 50 letters.
M> 1. #{5} without the flag '_' (allow spaces)
M> 2. ##|#|#|# '_' set for the first field, but not set for the other three
M> 3. C{50} '_' is set

I think (2) is really bad. It's completely counterintuitive and quite
non-discoverable. Again, I'd prefer just about anything else to this.

M> > 1. #{5}
M> > 2. #{3,5}
M> > 3. A{,50}
M> Shorter, yes. Regex may be more beautiful.
M>
M> What about this?:
M> # a digit or nothing
M> 0 a digit

I don't like this. It means we need to have 2 symbols for every class of
characters, one for "whatever" and one for "whatever or nothing". Using
some generic notation like "#?" or "#_" or something like this is IMO much
better.


M> Spaces are blurring me.

Spaces are different from "no entry" so here I think we could have
different classes for "letters" and "letters or space". But if we could use
a generic syntax it could be better too.

For example what about "[A ]" meaning "a letter or a space"? This could
also be used for e.g. "[#X]" which would be useful for ISBN entry (ISBNs
are mostly numbers but they may have "X" as the last "digit").

M> Suppose for some reason we have in a IP fleld the string "1 3".

If it's a number from one field, I don't see how is this possible, spaces
should be forbidden in it.

M> Now suppose we have a "first name" field. In Spanish a compound name
M> (i.e "Jose Antonio") is valid. So we can not delete the space (but we
M> can delete spaces at left & right).
M> I'm trying to tell how to treat these cases, either with the mask or
M> with some flag.

Trimming should probable be done with some (per-field) flag. But the main
difference between the two cases is that the spaces are not allowed at all
in the first case but allowed in the second one. I really don't see the
problem here.

M> If a right-align flag is set for that "first name" field,

Bad idea anyhow, right alignment is for numbers. But "right alignment"
doesn't mean "trim spaces on the right", these are 2 different things! You
can have one without the other (and vice versa) and there is also a big
difference between them concerning time when they're used: "alignment" is
used while entering the entry, i.e. if you enter "Jose" in a 10 character
right aligned field it would display as "______Jose". But "trim" is only
used when accessing the field value (including when normalizing it on focus
loss), it must not be used while entering data in the field.

M> typing the space is impossible, because GetFielValue would always return
M> "Jose" because it deleted left-right spaces.

This is one of the reasons for the above but not the only one.

M> So GetFieldValue would not delete spaces, retuning always the whole
M> field, filled or not.

I think you're saying we need GetRawFieldValue() which returns exactly
what is entered into the control right now and GetFieldValue() which
returns the field contents after applying any flags, e.g. trimming. Why
not.


M> Also, if the control derives from wxWindow, wxFrame can take ownership
M> of the pointer and delete it when the window is closed.

This is a good point.


M> >  Why do we need accept and exclude lists at all? Aren't they redundant with
M> > the mask?
M> To allow a field which allows not only what is set from the mask, but
M> also other options. Example, a digit or one of "XM".

As I wrote above, this could be achieved simply by supporting "[#XM]"
syntax in the mask.

M> Other example: any char, except one of "abc"

This would then be "[.-abc]". Although I really wonder how useful would
this be. Definitely something for v2 (or vN...).

M> Other more: a 3-digits number, or one of the words "min" "max"

Simple accept/reject lists don't help here. You need a custom validator.


M> > M> The 5) step is, in wxMaskEdit, where the code calls the function
M> > M> defined for field/control.
M> > M> The user can replace the one predefined there with its own function.
M> >
M> >  I think in C++ it would be natural to have a virtual function to do the
M> > check. Then you could override it and call the base class version either
M> > before or after your own code (or not at all) so that you could choose any
M> > order you want.
M> wxMaskEdit will have some predefined functions, as public members.
M> For example, DayCheck(...) returning false if not in the [1-31]
M> range.

This looks unnecessarily specific. If you wanted to provide such helpers,
I'd rather have IsIntegerInRange(int min, int max). But this is again
something for v2 IMHO.

M> And here are two ways:
M> - We define SetFieldFunction(ExFun), where ExFun is a function that
M> has a wxMaskEdit * parameter.

The callback should probably take wxString (the field value) and not
wxMaskEdit.

Regards,
VZ

Manolo

unread,
May 30, 2012, 8:33:57 PM5/30/12
to wx-...@googlegroups.com
> M> What about this?:
> M>   #   a digit or nothing
> M>   0   a digit
>
>  I don't like this. It means we need to have 2 symbols for every class of
> characters, one for "whatever" and one for "whatever or nothing". Using
If we have two different inputs, we need two different notations. If we have
n different inputs, either we have n notations or x notations and y modifiers.

> some generic notation like "#?" or "#_" or something like this is IMO much
> better.
What, as much exactly as possible (you are very good at this), means the
question mark? If it is a mask command for "whatever or nothing" your proposal
also duplicate symbols. If it is a modifier for a mask command,
applies it to any
other mask command?
How do you set 'force uppercase and allow an space'?

> M> Spaces are blurring me.
>
>  Spaces are different from "no entry" so here I think we could have
> different classes for "letters" and "letters or space". But if we could use
> a generic syntax it could be better too.
Again duplicating symbols. We hardly can avoid it.

>  For example what about "[A ]" meaning "a letter or a space"? This could
> also be used for e.g. "[#X]" which would be useful for ISBN entry (ISBNs
> are mostly numbers but they may have "X" as the last "digit").
I would understand that 'X' as a literal. The user will see it, but
will not type it.
By the way, the last char in a ISBN code is a [0-9] digit or the 'X' char.

> M> Suppose for some reason we have in a IP fleld the string "1 3".
>
>  If it's a number from one field, I don't see how is this possible, spaces
> should be forbidden in it.
Yes. But if the user types '1' and the moves right-most with the cursor and
types '3', he has not typed any space. Is the field function job to
join the digits.

>  I think you're saying we need GetRawFieldValue() which returns exactly
> what is entered into the control right now and GetFieldValue() which
> returns the field contents after applying any flags, e.g. trimming. Why
> not.
Good point.

> M> Also, if the control derives from wxWindow, wxFrame can take ownership
> M> of the pointer and delete it when the window is closed.
>
>  This is a good point.
Anyone against control approach, deriving from wxTextCtrl/wxCombobox?
If none, I'll implement it this way.


> M> >  Why do we need accept and exclude lists at all? Aren't they redundant with
> M> > the mask?
> M> To allow a field which allows not only what is set from the mask, but
> M> also other options. Example, a digit or one of "XM".
>
>  As I wrote above, this could be achieved simply by supporting "[#XM]"
> syntax in the mask.
In ISBN sample, the last digit will be a 1-char length field (with '#'
command), and
an array of choices with just only one item: 'X'

> M> Other example: any char, except one of "abc"
>
>  This would then be "[.-abc]". Although I really wonder how useful would
> this be. Definitely something for v2 (or vN...).
It is very clear you love regexes.
But the initial idea for this wxMaskedEdit is allowing other kind of "mask",
defined mostly char by char. I suggest (again) having both features, setting
the mask from 'char by char' or from a regex.

> M> Other more: a 3-digits number, or one of the words "min" "max"
>
>  Simple accept/reject lists don't help here. You need a custom validator.
Well. I said it.
IMHO, we need to clarify what an user will see on screen.
Case 1: typing a number, e.g. an IP field.
The cursor is in the left part of the field.The user types '1'. What do we do?
We validate the char, yes. And we can also validate the field, so we can
set a color for the control. But then, move the char to right most in the field?
Move the cursor where? Do nothing?. Next he types '2'.  Same questions.
Case 2: a letters field. Its behavior may be different, mainly because of
spaces and field validation.

What checks do we when? We have three levels for checking (char, field,
control) and two opportunities: for key/char events and when the field/control
loses the focus. TAB key is a command to lose focus.
IMO, key/char events are useful for filtering inputs. Perhaps also for field
normalizing. TAB/focus will do full check, but without filtering.

> M> wxMaskEdit will have some predefined functions, as public members.
> M> For example,  DayCheck(...) returning false if not in the [1-31]
> M> range.
>
>  This looks unnecessarily specific. If you wanted to provide such helpers,
> I'd rather have IsIntegerInRange(int min, int max). But this is again
> something for v2 IMHO.
Yes, IsInRange() will, for sure, one of those predefined functions. I wrote
DayCheck as an example. One more complex would be DateCheck, for
a group of fields, checking each on and the group (leap years, etc)
I'll write simple 'checkers' for version 1.

> M> And here are two ways:
> M> - We define SetFieldFunction(ExFun), where ExFun is a function that
> M> has a wxMaskEdit * parameter.
>
>  The callback should probably take wxString (the field value) and not
> wxMaskEdit.
That was my first idea. But then I noticed the field value would be checked
depending also on other fields. (e.g. 'X' in the ISBN). And if the
user's function
needs to call some of the predefined functions, well, passing a pointer to our
object would help him a lot.
But if our predefined are public, then the user just need to know the
index field.
ExFun(index) would be enough.

Regards
Manolo

Manolo

unread,
May 30, 2012, 8:48:13 PM5/30/12
to wx-...@googlegroups.com
After 25 post in this thread, I notice just Werner wanted to say something.
It's a really pity the low participation. So is people. We must accept this.

Vadim proves, once more, why he is "wx hero" (Julian said it).
Administrates, tests, writes code, fixes bugs... and after all finds
time to think and discuss most of subjects.

Thank you very much Vadim.
Regards
Manolo

Vadim Zeitlin

unread,
May 31, 2012, 9:20:52 AM5/31/12
to wx-...@googlegroups.com
On Thu, 31 May 2012 02:33:57 +0200 Manolo wrote:

M> > M> What about this?:
M> > M>   #   a digit or nothing
M> > M>   0   a digit
M> >
M> >  I don't like this. It means we need to have 2 symbols for every class of
M> > characters, one for "whatever" and one for "whatever or nothing". Using
M> If we have two different inputs, we need two different notations. If we have
M> n different inputs, either we have n notations or x notations and y modifiers.

To be more concrete, I think we need to support at least the following
categories:

1. Any (printable) character.
2. A letter.
3. A letter or digit.
4. A digit.
5. A hexadecimal digit.

So if we don't use a generic syntax for "something or nothing" we'd need 10
different characters right here. Not only would this be difficult to
remember but I also think we'd risk running out of 26 letters quite quickly
at this rate.

M> > some generic notation like "#?" or "#_" or something like this is IMO much
M> > better.
M> What, as much exactly as possible (you are very good at this), means the
M> question mark? If it is a mask command for "whatever or nothing" your
M> proposal also duplicate symbols. If it is a modifier for a mask command,
M> applies it to any other mask command?

I don't understand what is the problem with duplication with this
approach. "?" is for me orthogonal to the normal mask characters. I.e.,
again, if we use "#" for a digit and "A" for a letter then we'd use "#?"
for an optional digit and "A?" for an optional letter.

M> How do you set 'force uppercase and allow an space'?

I thought that "force upper case" would be a global, or at least
per-field, flag. I have trouble imagining a realistic scenario in which
you'd want to make only some letters in a field upper case.

As for "allow a space", we could use either the general syntax with
"[...]" below or use "A_" to mean "letter or space or nothing" (I don't
think it makes sense to make a character required if you can use a space).

M> >  For example what about "[A ]" meaning "a letter or a space"? This could
M> > also be used for e.g. "[#X]" which would be useful for ISBN entry (ISBNs
M> > are mostly numbers but they may have "X" as the last "digit").
M> I would understand that 'X' as a literal. The user will see it, but
M> will not type it.

Sorry, I don't understand this. What is the problem exactly?

M> By the way, the last char in a ISBN code is a [0-9] digit or the 'X' char.

Err, yes, this is what I wrote, didn't I? Sorry if I'm missing something
here...


M> > M> Suppose for some reason we have in a IP fleld the string "1 3".
M> >
M> >  If it's a number from one field, I don't see how is this possible, spaces
M> > should be forbidden in it.
M> Yes. But if the user types '1' and the moves right-most with the cursor and
M> types '3', he has not typed any space. Is the field function job to
M> join the digits.

No, I don't think so. If WXK_RIGHT is pressed, the focus switches to the
next field. So after the key sequence above you'd have "__1.__3.___.___" in
the control. Again, what's the problem?

M> > M> Also, if the control derives from wxWindow, wxFrame can take ownership
M> > M> of the pointer and delete it when the window is closed.
M> >
M> >  This is a good point.
M> Anyone against control approach, deriving from wxTextCtrl/wxCombobox?
M> If none, I'll implement it this way.

OK but, again, please make it just a very thin class simply connecting
wxMaskEdit to the real control. I.e. all the functionality that doesn't
need to be in wxMaskEditCtrl should be in wxMaskEdit.


M> But the initial idea for this wxMaskedEdit is allowing other kind of "mask",
M> defined mostly char by char.

Yes, this is true. Maybe I'm indeed overcomplicating things. I didn't
really want to go into the mask syntax discussion at all, I'd gladly accept
another proposal. But I'd like to see some consistency in it and the idea
with "|" still doesn't make much sense to me.

Perhaps we should stop this thread and you should post your full proposed
mask syntax in a new one.

M> I suggest (again) having both features, setting the mask from 'char by
M> char' or from a regex.

We can't use arbitrary regexes for this, it's impossible (think of
alterations or unbounded repetitions). I just wanted to reuse some of the
simple parts of the regex syntax, nothing more.


M> Case 1: typing a number, e.g. an IP field.
M> The cursor is in the left part of the field.The user types '1'. What do we do?
M> We validate the char, yes. And we can also validate the field, so we can
M> set a color for the control. But then, move the char to right most in the field?
M> Move the cursor where? Do nothing?. Next he types '2'.  Same questions.

The desired behaviour here is pretty clear and I really don't see the
problem: when the cursor is in a field of max width N, you don't do
anything at all as long as less than N characters are entered into it. When
N-th character is entered, you move the cursor to the beginning of the next
field. What's the problem?

M> Case 2: a letters field. Its behavior may be different, mainly because of
M> spaces and field validation.

The only difference is in the alignment.

M> What checks do we when? We have three levels for checking (char, field,
M> control) and two opportunities: for key/char events and when the field/control
M> loses the focus. TAB key is a command to lose focus.
M> IMO, key/char events are useful for filtering inputs. Perhaps also for field
M> normalizing. TAB/focus will do full check, but without filtering.

Yes.

Regards,
VZ

Robin Dunn

unread,
May 31, 2012, 12:33:34 PM5/31/12
to wx-...@googlegroups.com
On 5/30/12 5:48 PM, Manolo wrote:
> After 25 post in this thread, I notice just Werner wanted to say something.
> It's a really pity the low participation. So is people. We must accept this.

Don't assume that unresponsiveness is the same as being uninterested.
It can also mean that people are in agreement with the way that the
conversation is going, enough so that they do not feel the need to pipe
up and give their own opinion about it.

--
Robin Dunn
Software Craftsman
http://wxPython.org

Manolo

unread,
May 31, 2012, 3:18:03 PM5/31/12
to wx-...@googlegroups.com
> Don't assume that unresponsiveness is the same as being uninterested. It can
> also mean that people are in agreement with the way that the conversation is
> going, enough so that they do not feel the need to pipe up and give their
> own opinion about it.
Yes, I agree with you.
But in my experience, that works only for a few people. Most of the
rest prefer to be behind the wall, and wait until they can get
something from it, instead of contribute some way. Even if this "some
way" means just an opinion.

Regards
Manolo
Reply all
Reply to author
Forward
0 new messages