Added wxEVT_TEXT_ENTER handling for TextCtrl, SpinCtrl & PointCtrl (but it doesn't work under OSX) (fix of #1518)

This commit is contained in:
YuSanka 2019-01-08 16:05:49 +01:00
parent 2ccdfe6853
commit 6efcdd1ddf
2 changed files with 72 additions and 37 deletions

View File

@ -66,12 +66,8 @@ void Field::PostInitialize()
BUILD(); BUILD();
} }
void Field::on_kill_focus(wxEvent& event) void Field::on_kill_focus()
{ {
// Without this, there will be nasty focus bugs on Windows.
// Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all
// non-command events to allow the default handling to take place."
event.Skip();
// call the registered function if it is available // call the registered function if it is available
if (m_on_kill_focus!=nullptr) if (m_on_kill_focus!=nullptr)
m_on_kill_focus(m_opt_id); m_on_kill_focus(m_opt_id);
@ -250,11 +246,23 @@ void TextCtrl::BUILD() {
break; break;
} }
const long style = m_opt.multiline ? wxTE_MULTILINE : 0; const long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER/*0*/;
auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style); auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style);
temp->SetToolTip(get_tooltip_text(text_value)); temp->SetToolTip(get_tooltip_text(text_value));
if (style == wxTE_PROCESS_ENTER) {
temp->Bind(wxEVT_TEXT_ENTER, ([this, temp](wxEvent& e)
{
#if !defined(__WXGTK__)
e.Skip();
temp->GetToolTip()->Enable(true);
#endif // __WXGTK__
propagate_value();
bEnterPressed = true;
}), temp->GetId());
}
temp->Bind(wxEVT_SET_FOCUS, ([this](wxEvent& e) { on_set_focus(e); }), temp->GetId()); temp->Bind(wxEVT_SET_FOCUS, ([this](wxEvent& e) { on_set_focus(e); }), temp->GetId());
temp->Bind(wxEVT_LEFT_DOWN, ([temp](wxEvent& event) temp->Bind(wxEVT_LEFT_DOWN, ([temp](wxEvent& event)
@ -272,14 +280,15 @@ void TextCtrl::BUILD() {
temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e) temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e)
{ {
#if !defined(__WXGTK__)
e.Skip(); e.Skip();
#if !defined(__WXGTK__)
temp->GetToolTip()->Enable(true); temp->GetToolTip()->Enable(true);
#endif // __WXGTK__ #endif // __WXGTK__
if (is_defined_input_value<wxTextCtrl>(window, m_opt.type)) if (bEnterPressed) {
on_change_field(); bEnterPressed = false;
else return;
on_kill_focus(e); }
propagate_value();
}), temp->GetId()); }), temp->GetId());
/* /*
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt) temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt)
@ -311,6 +320,14 @@ void TextCtrl::BUILD() {
window = dynamic_cast<wxWindow*>(temp); window = dynamic_cast<wxWindow*>(temp);
} }
void TextCtrl::propagate_value()
{
if (is_defined_input_value<wxTextCtrl>(window, m_opt.type))
on_change_field();
else
on_kill_focus();
}
boost::any& TextCtrl::get_value() boost::any& TextCtrl::get_value()
{ {
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue(); wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
@ -398,7 +415,7 @@ void SpinCtrl::BUILD() {
const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647;
auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size,
0, min_val, max_val, default_value); 0|wxTE_PROCESS_ENTER, min_val, max_val, default_value);
#ifndef __WXOSX__ #ifndef __WXOSX__
// #ys_FIXME_KILL_FOCUS // #ys_FIXME_KILL_FOCUS
@ -407,15 +424,23 @@ void SpinCtrl::BUILD() {
// and on TEXT event under OSX // and on TEXT event under OSX
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e)
{ {
if (tmp_value < 0)
on_kill_focus(e);
else {
e.Skip(); e.Skip();
on_change_field(); if (bEnterPressed) {
bEnterPressed = false;
return;
} }
propagate_value();
}), temp->GetId()); }), temp->GetId());
temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId());
temp->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e)
{
e.Skip();
propagate_value();
bEnterPressed = true;
}), temp->GetId());
#endif #endif
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e)
@ -430,12 +455,7 @@ void SpinCtrl::BUILD() {
tmp_value = std::stoi(value); tmp_value = std::stoi(value);
else tmp_value = -9999; else tmp_value = -9999;
#ifdef __WXOSX__ #ifdef __WXOSX__
if (tmp_value < 0) { propagate_value();
if (m_on_kill_focus != nullptr)
m_on_kill_focus(m_opt_id);
}
else
on_change_field();
#endif #endif
}), temp->GetId()); }), temp->GetId());
@ -445,6 +465,14 @@ void SpinCtrl::BUILD() {
window = dynamic_cast<wxWindow*>(temp); window = dynamic_cast<wxWindow*>(temp);
} }
void SpinCtrl::propagate_value()
{
if (tmp_value < 0)
on_kill_focus();
else
on_change_field();
}
void Choice::BUILD() { void Choice::BUILD() {
auto size = wxSize(wxDefaultSize); auto size = wxSize(wxDefaultSize);
if (m_opt.height >= 0) size.SetHeight(m_opt.height); if (m_opt.height >= 0) size.SetHeight(m_opt.height);
@ -483,7 +511,7 @@ void Choice::BUILD() {
on_change_field(); on_change_field();
} }
else else
on_kill_focus(e); on_kill_focus();
}), temp->GetId()); }), temp->GetId());
} }
@ -755,8 +783,8 @@ void PointCtrl::BUILD()
val = default_pt(1); val = default_pt(1);
wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None); wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None);
x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size); x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size, wxEVT_TEXT_ENTER);
y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size); y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size, wxEVT_TEXT_ENTER);
temp->Add(new wxStaticText(m_parent, wxID_ANY, "x : "), 0, wxALIGN_CENTER_VERTICAL, 0); temp->Add(new wxStaticText(m_parent, wxID_ANY, "x : "), 0, wxALIGN_CENTER_VERTICAL, 0);
temp->Add(x_textctrl); temp->Add(x_textctrl);
@ -766,8 +794,11 @@ void PointCtrl::BUILD()
// x_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), x_textctrl->GetId()); // x_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), x_textctrl->GetId());
// y_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), y_textctrl->GetId()); // y_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), y_textctrl->GetId());
x_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { OnKillFocus(e, x_textctrl); }), x_textctrl->GetId()); x_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(x_textctrl); }), x_textctrl->GetId());
y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { OnKillFocus(e, x_textctrl); }), y_textctrl->GetId()); y_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(y_textctrl); }), y_textctrl->GetId());
x_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_value(x_textctrl); }), x_textctrl->GetId());
y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_value(y_textctrl); }), y_textctrl->GetId());
// // recast as a wxWindow to fit the calling convention // // recast as a wxWindow to fit the calling convention
sizer = dynamic_cast<wxSizer*>(temp); sizer = dynamic_cast<wxSizer*>(temp);
@ -776,14 +807,12 @@ void PointCtrl::BUILD()
y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y)); y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y));
} }
void PointCtrl::OnKillFocus(wxEvent& e, wxTextCtrl* win) void PointCtrl::propagate_value(wxTextCtrl* win)
{ {
e.Skip(); if (!win->GetValue().empty())
if (!win->GetValue().empty()) {
on_change_field(); on_change_field();
}
else else
on_kill_focus(e); on_kill_focus();
} }
void PointCtrl::set_value(const Vec2d& value, bool change_event) void PointCtrl::set_value(const Vec2d& value, bool change_event)

View File

@ -74,7 +74,7 @@ protected:
/// Call the attached on_kill_focus method. /// Call the attached on_kill_focus method.
//! It's important to use wxEvent instead of wxFocusEvent, //! It's important to use wxEvent instead of wxFocusEvent,
//! in another case we can't unfocused control at all //! in another case we can't unfocused control at all
void on_kill_focus(wxEvent& event); void on_kill_focus();
/// Call the attached on_change method. /// Call the attached on_change method.
void on_set_focus(wxEvent& event); void on_set_focus(wxEvent& event);
/// Call the attached on_change method. /// Call the attached on_change method.
@ -227,6 +227,8 @@ protected:
// current value // current value
boost::any m_value; boost::any m_value;
bool bEnterPressed = false;
friend class OptionsGroup; friend class OptionsGroup;
}; };
@ -252,6 +254,8 @@ public:
~TextCtrl() {} ~TextCtrl() {}
void BUILD(); void BUILD();
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void propagate_value();
wxWindow* window {nullptr}; wxWindow* window {nullptr};
virtual void set_value(const std::string& value, bool change_event = false) { virtual void set_value(const std::string& value, bool change_event = false) {
@ -310,6 +314,8 @@ public:
wxWindow* window{ nullptr }; wxWindow* window{ nullptr };
void BUILD() override; void BUILD() override;
/// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void propagate_value() ;
void set_value(const std::string& value, bool change_event = false) { void set_value(const std::string& value, bool change_event = false) {
m_disable_change_event = !change_event; m_disable_change_event = !change_event;
@ -393,8 +399,8 @@ public:
wxTextCtrl* y_textctrl{ nullptr }; wxTextCtrl* y_textctrl{ nullptr };
void BUILD() override; void BUILD() override;
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void OnKillFocus(wxEvent& e, wxTextCtrl* win); void propagate_value(wxTextCtrl* win);
void set_value(const Vec2d& value, bool change_event = false); void set_value(const Vec2d& value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false);
boost::any& get_value() override; boost::any& get_value() override;