[wxPython] overiding wxPanel.Validate() seems to break custom Validators

HI,

I have several custom Validators (wxPyValidator children), they get called
and work. But, in a parent form if I create my own Validate() method
(representative example below) they are no longer called.

btw The effect I am after is to get in the containing window(wxPanel in this
case) a list of contrls that failed validation so that I can tell the user
what to fix.

thanks,
norm

class BaseForm(wxPanel, BaseCommon):
    def Validate(self):
        self._invalid_Ctrls = []
        for col in self._cols2ctrls.keys():
            ctrl = self._cols2ctrls[col]
            wxLogDebug("validating [%s]"%ctrl.GetName())

            #don't know what ctrl.Validate() does,
            #but it doesn't call ctrl.GetValidator().Validate()
            if not ctrl.Validate():
                wxLogDebug("failed validation [%s]"%ctrl.GetName())
                self._invalid_Ctrls.append(ctrl)
        return (len(self._invalid_Ctrls) == 0)

···

#---------------------------------------------------------------------------

class base_Validator(wxPyValidator):
    def __init__(self, dbi_desc_tuple):
        """
        dbi_desc_tuple dbi 2.0 desc tuple (name, type_code,
display_size, internal_size, precision, scale, null_ok)
        """
        wxPyValidator.__init__(self)
        self.t = dbi_desc_tuple
        EVT_CHAR(self, self.OnChar)

    def OnChar(self, event):
        key = event.KeyCode()
        if key < WXK_SPACE or key == WXK_DELETE or key > 255:
            event.Skip() #skip is return too

        ctrl = self.GetWindow()
        val = ctrl.GetValue()

        #this garbage is to make the value what it will be so that we can
try and validate it
        (s,e) = ctrl.GetSelection()
        if s==e: #start selection_idx==end selection_idx there is no
selection!
            val = val[:ctrl.GetInsertionPoint()] + chr(key) +
val[ctrl.GetInsertionPoint():]
        else: #need to replace current selection
            val = val[:s] + chr(key) + val[e:]

        if self.Validate(event.GetEventObject(), val):
            event.Skip()
        elif not wxValidator_IsSilent():
            wxBell()

class cur_numba_Validator(base_Validator):
    "Cursor based validator"
    def __init__(self, get_cursor_func, dbi_desc_tuple):
        """
        get_cursor_func returns the cursor for given control
        """
        base_Validator.__init__(self, dbi_desc_tuple)
        self.cur_func = get_cursor_func

    def Clone(self):
        return cur_numba_Validator(self.cur_func, self.t)

    def OnChar(self, event):
        key = event.KeyCode()
        if key == WXK_SPACE:
            return
        else:
            base_Validator.OnChar(self, event)

    def TransferToWindow(self):
        try:
            ctrl = self.GetWindow()
            value = self.cur_func()[ctrl.columnname]
(value))
            if value == None:
                ctrl.SetValue('')
            else:
                ctrl.SetValue( ("%%.%if" % self.t[5]) % float(value))
        except:
            wxLogException()

    def TransferFromWindow(self):
        try:
            ctrl = self.GetWindow()
            value = ctrl.GetValue().strip()
            if value in ('', None):
                self.cur_func()[ctrl.columnname] = None
            elif self.t[5] > 0: #if precision is > 0 we reckon its a float
type field
                self.cur_func()[ctrl.columnname] = float(value)
            else:
                self.cur_func()[ctrl.columnname] = int(value)
        except:
            wxLogException()
            pass

    def Validate(self, win, value=None):
        ctrl = self.GetWindow()
        if not value:
            value = ctrl.GetValue()
        if value in ('', None):
            if self.t[6]:
                return true
            else:
                wxLogDebug("%s null not ok" % (ctrl.GetName()) )
                return false
        if len(value) > self.t[3]:
            return false
        #check precession I have no idea why minus 2 instead of minus 1
        if value.find('.') > 0 and (len(value)-2)-value.find('.') >=
self.t[5]:
self.t[5]))
            return false
        try:
            if self.t[5] > 0:
                #if precision is > 0 we reckon its a float type field else
an int
                float(value)
            else:
                int(value)
            return true
        except ValueError:
            return false

I have several custom Validators (wxPyValidator children), they get called
and work. But, in a parent form if I create my own Validate() method
(representative example below) they are no longer called.

I have to add special (and fairly complex) code in order to fully support
overloading of virtual methods in Python derived classes, so most of them
are not done. Consequently, overloading Validate will probably not have the
effect you are looking for. You can still call it of course, but your
method won't be called by the framework. (However, 2.3.3 will support this
if you derive from wxPyPanel.)

btw The effect I am after is to get in the containing window(wxPanel in

this

case) a list of contrls that failed validation so that I can tell the user
what to fix.

Why not just have the Validator itself do the notification? It could do
this by calling some method in the parent panel, logging a message, or even
changing the colour of the control.

            #don't know what ctrl.Validate() does,
            #but it doesn't call ctrl.GetValidator().Validate()

bool wxWindowBase::Validate()
{
#if wxUSE_VALIDATORS
    bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;

    wxWindowList::Node *node;
    for ( node = m_children.GetFirst(); node; node = node->GetNext() )
    {
        wxWindowBase *child = node->GetData();
        wxValidator *validator = child->GetValidator();
        if ( validator && !validator->Validate((wxWindow *)this) )
        {
            return FALSE;
        }

        if ( recurse && !child->Validate() )
        {
            return FALSE;
        }
    }
#endif // wxUSE_VALIDATORS

    return TRUE;
}

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!