validate recursively problem

I have a problem that even after setting "WS_EX_VALIDATE_RECURSIVELY" children of children never get the InitDialog event.

The attached sample shows the problem, if one clicks the button "onInitDialog" is only called for the frame. In the past I worked around this by calling InitDialog on sub-panels but I really like to get to the buttom of this problem and get it to work correctly.

This is on Python 2.7.2 and wxPython 2.9.3.1 (aui is from SVN a few days ago).

Can anyone see what I am doing wrong?

Thanks in advance for any tips on this.

Werner

validaterecursively.py (8.03 KB)

It looks like it is not the initdialog event that is supposed to recurse, but rather the TransferDataToWindow calls. Here is the C++ code involved with this, first the InitDialog method:

void wxWindowBase::InitDialog()
{
     wxInitDialogEvent event(GetId());
     event.SetEventObject( this );
     GetEventHandler()->ProcessEvent(event);
}

This is the default handler for the EVT_INIT_DIALOG event, it calls TransferDataToWindow:

void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
{
     TransferDataToWindow();

     // Update the UI at this point
     UpdateWindowUI(wxUPDATE_UI_RECURSE);
}

And here is the transfer function. For every child of the window it gets the validator, and if there is one it calls the validator's TransferToWindow() method. Then if the recurse flag is set for this window it then calls the child's TransferDataToWindow method.

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

     wxWindowList::compatibility_iterator node;
     for ( node = m_children.GetFirst(); node; node = node->GetNext() )
     {
         wxWindowBase *child = node->GetData();
         wxValidator *validator = child->GetValidator();
         if ( validator && !validator->TransferToWindow() )
         {
             wxLogWarning(_("Could not transfer data to window"));
#if wxUSE_LOG
             wxLog::FlushActive();
#endif // wxUSE_LOG

             return false;
         }

         if ( recurse )
         {
             if ( !child->TransferDataToWindow() )
             {
                 // warning already given
                 return false;
             }
         }
     }
#endif // wxUSE_VALIDATORS

     return true;
}

So basically the InitDialog method and event are only involved at the top level. Everything below that uses the transfer methods.

···

On 2/15/12 2:46 AM, werner wrote:

I have a problem that even after setting "WS_EX_VALIDATE_RECURSIVELY"
children of children never get the InitDialog event.

The attached sample shows the problem, if one clicks the button
"onInitDialog" is only called for the frame. In the past I worked around
this by calling InitDialog on sub-panels but I really like to get to the
buttom of this problem and get it to work correctly.

This is on Python 2.7.2 and wxPython 2.9.3.1 (aui is from SVN a few days
ago).

Can anyone see what I am doing wrong?

Thanks in advance for any tips on this.

Werner

--
Robin Dunn
Software Craftsman

Hi Robin,

I have a problem that even after setting "WS_EX_VALIDATE_RECURSIVELY"
children of children never get the InitDialog event.

The attached sample shows the problem, if one clicks the button
"onInitDialog" is only called for the frame. In the past I worked around
this by calling InitDialog on sub-panels but I really like to get to the
buttom of this problem and get it to work correctly.

This is on Python 2.7.2 and wxPython 2.9.3.1 (aui is from SVN a few days
ago).

Can anyone see what I am doing wrong?

Thanks in advance for any tips on this.

Werner

It looks like it is not the initdialog event that is supposed to recurse, but rather the TransferDataToWindow calls. Here is the C++ code involved with this, first the InitDialog method:

void wxWindowBase::InitDialog()
{
    wxInitDialogEvent event(GetId());
    event.SetEventObject( this );
    GetEventHandler()->ProcessEvent(event);
}

This is the default handler for the EVT_INIT_DIALOG event, it calls TransferDataToWindow:

void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
{
    TransferDataToWindow();

    // Update the UI at this point
    UpdateWindowUI(wxUPDATE_UI_RECURSE);
}

And here is the transfer function. For every child of the window it gets the validator, and if there is one it calls the validator's TransferToWindow() method. Then if the recurse flag is set for this window it then calls the child's TransferDataToWindow method.

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

    wxWindowList::compatibility_iterator node;
    for ( node = m_children.GetFirst(); node; node = node->GetNext() )
    {
        wxWindowBase *child = node->GetData();
        wxValidator *validator = child->GetValidator();
        if ( validator && !validator->TransferToWindow() )
        {
            wxLogWarning(_("Could not transfer data to window"));
#if wxUSE_LOG
            wxLog::FlushActive();
#endif // wxUSE_LOG

            return false;
        }

        if ( recurse )
        {
            if ( !child->TransferDataToWindow() )
            {
                // warning already given
                return false;
            }
        }
    }
#endif // wxUSE_VALIDATORS

    return true;
}

So basically the InitDialog method and event are only involved at the top level. Everything below that uses the transfer methods.

O.K., so the sample doesn't show that TransferDataToWindow is in my case not happening, even so I set the extra style on the top wx.Frame.

Is the recursion being interrupted if a sub-window (panel, splitWindow, ....) doens't have the extra style set?

Will haven another look at this tomorrow and come up with another sample if I still can't make it work.

Werner

···

On 15/02/2012 19:52, Robin Dunn wrote:

On 2/15/12 2:46 AM, werner wrote:

Yes. It only goes down another level if the current window has the style set. If a child on the next level doesn't have the style set then that is the end of the recursion on that fork of the tree.

···

On 2/15/12 11:09 AM, werner wrote:

Is the recursion being interrupted if a sub-window (panel, splitWindow,
....) doens't have the extra style set?

--
Robin Dunn
Software Craftsman

Robin,

···

On 15/02/2012 20:17, Robin Dunn wrote:

On 2/15/12 11:09 AM, werner wrote:

Is the recursion being interrupted if a sub-window (panel, splitWindow,
....) doens't have the extra style set?

Yes. It only goes down another level if the current window has the style set. If a child on the next level doesn't have the style set then that is the end of the recursion on that fork of the tree.

Finally found it. I had missed a couple extra style settings, but my real problem was that I had not set the correct flag to tell the code which sets up the control to assign an appropriate validator:-[ .

So, next time I will check the basics first before hunting all over the place, at least I hope I will;-) .

Werner