TransferToWindow and TransferFromWindow isn't called in custom validator Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
usernameak
In need of some credit
In need of some credit
Posts: 5
Joined: Thu Jul 12, 2018 11:13 am

TransferToWindow and TransferFromWindow isn't called in custom validator

Post by usernameak »

TransferToWindow and TransferFromWindow isn't called in custom validator.
The validator:

Code: Select all

#pragma once

#include <wx/wx.h>

template <typename T> class WDEdCBBitValidator : public wxValidator {
    T *val;
    T bitmask;
public:
    WDEdCBBitValidator(T *val, T bitmask) : wxValidator(), val(val), bitmask(bitmask) {
        wxPrintf("Validator init\n");
    };

    virtual wxObject *Clone() const {
        wxPrintf("Validator Clone %p %p\n", m_validatorWindow, val);
        return new WDEdCBBitValidator<T>(*this);
    }

    // Called when the value in the window must be validated: this is not used
    // by this class
    virtual bool Validate(wxWindow * WXUNUSED(parent)) {
        return true;
    }

    // Called to transfer data to the window
    virtual bool TransferToWindow() {
        wxPrintf("TransferToWindow %p %p\n", m_validatorWindow, val);
        if(!m_validatorWindow || !val) return false;
        wxCheckBox *cb = (wxCheckBox *) m_validatorWindow;
        cb->SetValue((*val & bitmask) ? true : false);
        return true;
    }

    // Called to transfer data from the window
    virtual bool TransferFromWindow() {
        wxPrintf("TransferFromWindow %p %p\n", m_validatorWindow, val);
        if(!m_validatorWindow || !val) return false;
        wxCheckBox *cb = (wxCheckBox *) m_validatorWindow;
        if(cb->GetValue()) {
            *val |= bitmask;
        } else {
            *val &= ~bitmask;
        }
        return true;
    }
};
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: TransferToWindow and TransferFromWindow isn't called in custom validator

Post by doublemax »

At first sight i don't see anything obviously wrong. Where/how do you use it? TransferToWindow() will only be called automatically inside wxDialog(s), not inside wxFrame(s).

http://docs.wxwidgets.org/trunk/overview_validator.html
Use the source, Luke!
usernameak
In need of some credit
In need of some credit
Posts: 5
Joined: Thu Jul 12, 2018 11:13 am

Re: TransferToWindow and TransferFromWindow isn't called in custom validator

Post by usernameak »

I use it in a wxDialog:

Code: Select all

template <typename T> WDEdPropertiesDialog *AddBitCheckboxGroup(wxString name, T *value, std::initializer_list<WDEdBitCheckboxProperties<T> > props) {
        AddGroup(name);
        int i = 0;
        int j = sizer->GetRows();
        for(auto &prop : props) {

            sizer->Add(new wxCheckBox(panel,
                                      wxID_ANY,
                                      prop.name,
                                      wxDefaultPosition, wxDefaultSize,
                                      0L,
                                      WDEdCBBitValidator<T>(value, prop.bitmask)
                                     ), wxGBPosition(j, i++));
            if(i != i % 4) {
                j++;
                i = i % 4;
            }
        }
        return this;
    }
Last edited by usernameak on Thu Jul 12, 2018 1:10 pm, edited 1 time in total.
Manolo
Can't get richer than this
Can't get richer than this
Posts: 828
Joined: Mon Apr 30, 2012 11:07 pm

Re: TransferToWindow and TransferFromWindow isn't called in custom validator

Post by Manolo »

Your validator code seems good. You don't post the code where the validator is bound or used, so hard to find an issue.

Transfer to/from window only happens automatically for dialogs, not other windows like a wxFrame.
You may call those functions as a response to some user action, e.g. the control loses focus.
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: TransferToWindow and TransferFromWindow isn't called in custom validator

Post by PB »

"Is not called in custom validator" implies that it works with a built-in one (wxGenericValidator)? This is quite important distinction to see whether the issue is with validation of your dialog in general or the custom validator only.

As usual, an SSCCE would be great to have...

Edit
Seems to works for me (as in both methods are getting called) with current master on MSW:

Code: Select all

#include <wx/wx.h>

template <typename T> class WDEdCBBitValidator : public wxValidator {
    T *val;
    T bitmask;
public:
    WDEdCBBitValidator(T *val, T bitmask) : wxValidator(), val(val), bitmask(bitmask) {
        wxLogMessage("Validator init\n");
    };

    virtual wxObject *Clone() const {
        wxLogMessage("Validator Clone %p %p\n", m_validatorWindow, val);
        return new WDEdCBBitValidator<T>(*this);
    }

    // Called when the value in the window must be validated: this is not used
    // by this class
    virtual bool Validate(wxWindow * WXUNUSED(parent)) {
        return true;
    }

    // Called to transfer data to the window
    virtual bool TransferToWindow() {
        wxLogMessage("TransferToWindow %p %p\n", m_validatorWindow, val);
        if(!m_validatorWindow || !val) return false;
        wxCheckBox *cb = (wxCheckBox *) m_validatorWindow;
        cb->SetValue((*val & bitmask) ? true : false);
        return true;
    }

    // Called to transfer data from the window
    virtual bool TransferFromWindow() {
        wxLogMessage("TransferFromWindow %p %p\n", m_validatorWindow, val);
        if(!m_validatorWindow || !val) return false;
        wxCheckBox *cb = (wxCheckBox *) m_validatorWindow;
        if(cb->GetValue()) {
            *val |= bitmask;
        } else {
            *val &= ~bitmask;
        }
        return true;
    }
};

class MyDialog : public wxDialog
{
public:
    MyDialog(int& value) : wxDialog(NULL, wxID_ANY, _("Test"))
    {        
        wxBoxSizer* bSizer = new wxBoxSizer(wxVERTICAL);

        wxTextCtrl* logCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);        
        wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));    

        wxCheckBox* cb = new wxCheckBox(this, wxID_ANY, "Checkbox",
                            wxDefaultPosition, wxDefaultSize, 0L, 
                            WDEdCBBitValidator<int>(&value,  0xFFFF));
        
        bSizer->Add(cb, 0);
        bSizer->Add(logCtrl, 1, wxEXPAND | wxALL, 5);                
        bSizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxALL, 5);

        wxLogMessage("Value is %d", value);

        SetSizer(bSizer);
    }	
};

class MyApp : public wxApp
{
public:
    virtual bool OnInit()
    {
        int value = 1;
        
        if ( MyDialog(value).ShowModal() == wxID_OK )
            wxMessageBox(wxString::Format("New value is %d", value));

        return false;
    }
}; wxIMPLEMENT_APP(MyApp);
I assume the issue is not something silly like using older wxWidgets and not setting wxWS_EX_VALIDATE_RECURSIVELY where necessary...
usernameak
In need of some credit
In need of some credit
Posts: 5
Joined: Thu Jul 12, 2018 11:13 am

Re: TransferToWindow and TransferFromWindow isn't called in custom validator

Post by usernameak »

PB wrote:"Is not called in custom validator" implies that it works with a built-in one (wxGenericValidator)? This is quite important distinction to see whether the issue is with validation of your dialog in general or the custom validator only.
I assume the issue is not something silly like using older wxWidgets and not setting wxWS_EX_VALIDATE_RECURSIVELY where necessary...
It works with wxIntegerValidator.
My version is 3.0.4
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: TransferToWindow and TransferFromWindow isn't called in custom validator

Post by PB »

Does the code from my previous post work on your setup, i.e., the method are called?
usernameak
In need of some credit
In need of some credit
Posts: 5
Joined: Thu Jul 12, 2018 11:13 am

Re: TransferToWindow and TransferFromWindow isn't called in custom validator

Post by usernameak »

PB wrote:Does the code from my previous post work on your setup, i.e., the method are called?
It does.
usernameak
In need of some credit
In need of some credit
Posts: 5
Joined: Thu Jul 12, 2018 11:13 am

Re: TransferToWindow and TransferFromWindow isn't called in custom validator

Post by usernameak »

wxWS_EX_VALIDATE_RECURSIVELY fixed the problem
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: TransferToWindow and TransferFromWindow isn't called in custom validator

Post by PB »

usernameak wrote:It works with wxIntegerValidator.
usernameak wrote:wxWS_EX_VALIDATE_RECURSIVELY fixed the problem
This is odd, no validator should have worked without the flag. Well, I guess all's well that ends well...
Post Reply