wxTextCtrl: wxNumValidator not Working after Paste, Delete, and Backspace

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
spiffy
Earned a small fee
Earned a small fee
Posts: 15
Joined: Wed Dec 13, 2017 6:24 pm

wxTextCtrl: wxNumValidator not Working after Paste, Delete, and Backspace

Post by spiffy » Sun Sep 01, 2019 10:06 pm

Hi:

Development Setup
Windows 8.1 x64
wxWidgets-3.1.0 (Static)
Visual Studio C++

Synopsis
When pasting or deleting (del or backspace) text that is validated by wxNumValidator (int or float), validation is not performed after the text has changed. Example:

Code: Select all

	wxIntegerValidator<unsigned long> validateInt(0, wxNUM_VAL_DEFAULT);
	validateInt.SetRange(5, 1000);
	wxTextCtrl _edit.Create(..., &validateInt);
... using the above code, if you set the text of _edit to "050" and then cursor to after the five, hit backspace, and you have "00", which is invalid.

Details
I've read various (mostly ancient) posts and didn't see a specific solution. Seems like everything suggested was just situational workarounds. I followed the code at wxNumValidatorBase::OnChar() and specific character ranges are intentionally ignored.

valnum.cpp:143:

Code: Select all

    if ( ch < WXK_SPACE || ch == WXK_DELETE )
    {
        // Allow ASCII control characters and Delete.
        return;
    }
This does make sense from a certain logic angle, however it creates an obvious problem with the text being invalid after the changes propagate.

Is there an easy solution to this problem that I missed? Admittedly, I am really tired and could have missed something simple.

Thanks!
Last edited by spiffy on Mon Sep 02, 2019 12:56 am, edited 4 times in total.

spiffy
Earned a small fee
Earned a small fee
Posts: 15
Joined: Wed Dec 13, 2017 6:24 pm

Re: wxTextCtrl: wxNumValidator not Working after Paste, Delete, and Backspace

Post by spiffy » Sun Sep 01, 2019 10:19 pm

Final workaround edit. No flags. Just creates a substring of the new string with the last char removed and creates a mock keypress for the new string. Should work for any text-change scenario (paste, del/backspace, and others). Restores the cursor position. Still optimistic for a more elegant solution 8)

Code: Select all

// wxEVT_KEY_DOWN
void TextCtrl::OnEditKeyDown(wxKeyEvent &event){
	_edit_value_prev = _edit.GetValue();
	event.Skip();
}

// wxEVT_TEXT
void TextCtrl::OnEditText(wxCommandEvent &event){
	if (_edit.GetValidator() && _edit.GetValue().Length() && _edit_value_prev.Length() && _edit_value_prev != _edit.GetValue()){
		_edit.Unbind(wxEVT_TEXT, wxCommandEventHandler(TextCtrl::OnEditText), this);

		wxString edit_value_new = _edit.GetValue();
		wxString edit_value_substr = edit_value_new.SubString(0, edit_value_new.Length() - 2);
		wxChar last_char = edit_value_new.GetChar(edit_value_new.Length() - 1);
		long cursor_pos = _edit.GetInsertionPoint();

		// prepare text ctrl for re-validation...
		_edit.SetValue(edit_value_substr);
		_edit.SetInsertionPoint(-1);	// set caret at end
		// validate using mock object...
		wxKeyEvent evt_validate(wxEVT_CHAR);
		evt_validate.SetEventObject(&_edit);
		evt_validate.SetEventType(wxEVT_CHAR);
		evt_validate.m_keyCode = last_char;
		evt_validate.m_uniChar = last_char;
		_edit.GetEventHandler()->ProcessEvent(evt_validate);
		// check results: true on valid...
		if (evt_validate.GetSkipped())
			 _edit.SetValue(edit_value_new);
		else _edit.SetValue(_edit_value_prev);

		// restore cursor position if in range...
		if (cursor_pos >= _edit.GetValue().Length())
			cursor_pos  = -1;
		_edit.SetInsertionPoint(cursor_pos);
		
		_edit.Bind(wxEVT_TEXT, wxCommandEventHandler(TextCtrl::OnEditText), this);
	}
	event.Skip();
}

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3402
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxTextCtrl: wxNumValidator not Working after Paste, Delete, and Backspace

Post by ONEEYEMAN » Tue Sep 03, 2019 2:21 pm

Hi,
There is a re-work of a wxValidators in the GitHub PR queue.

Hopefully when this is available it won't happen anymore.

You can grab the appropriate branch and try it - check the wxWidgets GitHub repo.

Thank you.

spiffy
Earned a small fee
Earned a small fee
Posts: 15
Joined: Wed Dec 13, 2017 6:24 pm

Re: wxTextCtrl: wxNumValidator not Working after Paste, Delete, and Backspace

Post by spiffy » Tue Sep 03, 2019 4:37 pm

That's great news. I will check it out. Thanks.

Post Reply