From 6efcdd1ddf5bd57b110370cc314f275cded3fb2d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 8 Jan 2019 16:05:49 +0100 Subject: [PATCH] Added wxEVT_TEXT_ENTER handling for TextCtrl, SpinCtrl & PointCtrl (but it doesn't work under OSX) (fix of #1518) --- src/slic3r/GUI/Field.cpp | 97 ++++++++++++++++++++++++++-------------- src/slic3r/GUI/Field.hpp | 12 +++-- 2 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 91052570d..2c7bce613 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -66,12 +66,8 @@ void Field::PostInitialize() 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 if (m_on_kill_focus!=nullptr) m_on_kill_focus(m_opt_id); @@ -250,11 +246,23 @@ void TextCtrl::BUILD() { 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); 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_LEFT_DOWN, ([temp](wxEvent& event) @@ -272,14 +280,15 @@ void TextCtrl::BUILD() { temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e) { -#if !defined(__WXGTK__) e.Skip(); +#if !defined(__WXGTK__) temp->GetToolTip()->Enable(true); #endif // __WXGTK__ - if (is_defined_input_value(window, m_opt.type)) - on_change_field(); - else - on_kill_focus(e); + if (bEnterPressed) { + bEnterPressed = false; + return; + } + propagate_value(); }), temp->GetId()); /* temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt) @@ -311,6 +320,14 @@ void TextCtrl::BUILD() { window = dynamic_cast(temp); } +void TextCtrl::propagate_value() +{ + if (is_defined_input_value(window, m_opt.type)) + on_change_field(); + else + on_kill_focus(); +} + boost::any& TextCtrl::get_value() { wxString ret_str = static_cast(window)->GetValue(); @@ -398,7 +415,7 @@ void SpinCtrl::BUILD() { const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; 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__ // #ys_FIXME_KILL_FOCUS @@ -407,15 +424,23 @@ void SpinCtrl::BUILD() { // and on TEXT event under OSX temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { - if (tmp_value < 0) - on_kill_focus(e); - else { - e.Skip(); - on_change_field(); + e.Skip(); + if (bEnterPressed) { + bEnterPressed = false; + return; } + + propagate_value(); }), 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 temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) @@ -430,12 +455,7 @@ void SpinCtrl::BUILD() { tmp_value = std::stoi(value); else tmp_value = -9999; #ifdef __WXOSX__ - if (tmp_value < 0) { - if (m_on_kill_focus != nullptr) - m_on_kill_focus(m_opt_id); - } - else - on_change_field(); + propagate_value(); #endif }), temp->GetId()); @@ -445,6 +465,14 @@ void SpinCtrl::BUILD() { window = dynamic_cast(temp); } +void SpinCtrl::propagate_value() +{ + if (tmp_value < 0) + on_kill_focus(); + else + on_change_field(); +} + void Choice::BUILD() { auto size = wxSize(wxDefaultSize); if (m_opt.height >= 0) size.SetHeight(m_opt.height); @@ -483,7 +511,7 @@ void Choice::BUILD() { on_change_field(); } else - on_kill_focus(e); + on_kill_focus(); }), temp->GetId()); } @@ -755,8 +783,8 @@ void PointCtrl::BUILD() val = default_pt(1); 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); - y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, 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, wxEVT_TEXT_ENTER); temp->Add(new wxStaticText(m_parent, wxID_ANY, "x : "), 0, wxALIGN_CENTER_VERTICAL, 0); 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()); // 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()); - y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { OnKillFocus(e, x_textctrl); }), y_textctrl->GetId()); + x_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(x_textctrl); }), x_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 sizer = dynamic_cast(temp); @@ -776,14 +807,12 @@ void PointCtrl::BUILD() 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(); - } else - on_kill_focus(e); + on_kill_focus(); } void PointCtrl::set_value(const Vec2d& value, bool change_event) diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 4a19b6103..bcc94c7ba 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -74,7 +74,7 @@ protected: /// Call the attached on_kill_focus method. //! It's important to use wxEvent instead of wxFocusEvent, //! 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. void on_set_focus(wxEvent& event); /// Call the attached on_change method. @@ -226,6 +226,8 @@ protected: // current value boost::any m_value; + + bool bEnterPressed = false; friend class OptionsGroup; }; @@ -252,6 +254,8 @@ public: ~TextCtrl() {} void BUILD(); + // Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER + void propagate_value(); wxWindow* window {nullptr}; virtual void set_value(const std::string& value, bool change_event = false) { @@ -310,6 +314,8 @@ public: wxWindow* window{ nullptr }; 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) { m_disable_change_event = !change_event; @@ -393,8 +399,8 @@ public: wxTextCtrl* y_textctrl{ nullptr }; void BUILD() override; - - void OnKillFocus(wxEvent& e, wxTextCtrl* win); + // Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER + void propagate_value(wxTextCtrl* win); void set_value(const Vec2d& value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false); boost::any& get_value() override;