Update value inside TextCtrl & SpinCtrl after wxEVT_KILL_FOCES instead of wxEVT_TEXT (or wxEVT_TEXT_ENTER)

This commit is contained in:
YuSanka 2018-12-11 13:34:37 +01:00
parent c4e334f863
commit d7bc1410ee
8 changed files with 68 additions and 47 deletions

View file

@ -74,7 +74,7 @@ void Field::on_kill_focus(wxEvent& event)
event.Skip(); 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_on_kill_focus(m_opt_id);
} }
void Field::on_change_field() void Field::on_change_field()
@ -125,9 +125,9 @@ void Field::get_value_by_opt_type(wxString& str)
case coPercents: case coPercents:
case coFloats: case coFloats:
case coFloat:{ case coFloat:{
if (m_opt.type == coPercent && str.Last() == '%') if (m_opt.type == coPercent && !str.IsEmpty() && str.Last() == '%')
str.RemoveLast(); str.RemoveLast();
else if (str.Last() == '%') { else if (!str.IsEmpty() && str.Last() == '%') {
wxString label = m_Label->GetLabel(); wxString label = m_Label->GetLabel();
if (label.Last() == '\n') label.RemoveLast(); if (label.Last() == '\n') label.RemoveLast();
while (label.Last() == ' ') label.RemoveLast(); while (label.Last() == ' ') label.RemoveLast();
@ -162,7 +162,7 @@ void Field::get_value_by_opt_type(wxString& str)
} }
} }
bool TextCtrl::is_defined_input_value() bool TextCtrl::is_defined_input_value() const
{ {
if (static_cast<wxTextCtrl*>(window)->GetValue().empty() && m_opt.type != coString && m_opt.type != coStrings) if (static_cast<wxTextCtrl*>(window)->GetValue().empty() && m_opt.type != coString && m_opt.type != coStrings)
return false; return false;
@ -216,7 +216,7 @@ void TextCtrl::BUILD() {
break; break;
} }
const long style = m_opt.multiline ? wxTE_MULTILINE : 0 | m_process_enter ? wxTE_PROCESS_ENTER : 0; const long style = m_opt.multiline ? wxTE_MULTILINE : 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));
@ -240,17 +240,13 @@ void TextCtrl::BUILD() {
e.Skip(); e.Skip();
temp->GetToolTip()->Enable(true); temp->GetToolTip()->Enable(true);
#endif // __WXGTK__ #endif // __WXGTK__
if (!is_defined_input_value()) // if (!is_defined_input_value())
if (is_defined_input_value())
on_change_field();
else
on_kill_focus(e); on_kill_focus(e);
}), temp->GetId()); }), temp->GetId());
/*
if (m_process_enter) {
temp->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent& evt) {
if(is_defined_input_value())
on_change_field();
}), temp->GetId());
}
else {
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt) temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt)
{ {
#ifdef __WXGTK__ #ifdef __WXGTK__
@ -267,8 +263,7 @@ void TextCtrl::BUILD() {
temp->Bind(wxEVT_KEY_DOWN, &TextCtrl::change_field_value, this); temp->Bind(wxEVT_KEY_DOWN, &TextCtrl::change_field_value, this);
temp->Bind(wxEVT_KEY_UP, &TextCtrl::change_field_value, this); temp->Bind(wxEVT_KEY_UP, &TextCtrl::change_field_value, this);
#endif //__WXGTK__ #endif //__WXGTK__
} */
// select all text using Ctrl+A // select all text using Ctrl+A
temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event) temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event)
{ {
@ -371,7 +366,15 @@ void SpinCtrl::BUILD() {
0, min_val, max_val, default_value); 0, min_val, max_val, default_value);
// temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { tmp_value = undef_spin_val; on_change_field(); }), temp->GetId()); // temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { tmp_value = undef_spin_val; on_change_field(); }), temp->GetId());
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { on_kill_focus(e); }), temp->GetId()); temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e)
{
if (tmp_value < 0)
on_kill_focus(e);
else {
e.Skip();
on_change_field();
}
}), temp->GetId());
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e)
{ {
// # On OSX / Cocoa, wxSpinCtrl::GetValue() doesn't return the new value // # On OSX / Cocoa, wxSpinCtrl::GetValue() doesn't return the new value
@ -382,7 +385,8 @@ void SpinCtrl::BUILD() {
std::string value = e.GetString().utf8_str().data(); std::string value = e.GetString().utf8_str().data();
if (is_matched(value, "^\\d+$")) if (is_matched(value, "^\\d+$"))
tmp_value = std::stoi(value); tmp_value = std::stoi(value);
on_change_field(); else tmp_value = -9999;
// on_change_field();
// # We don't reset tmp_value here because _on_change might put callbacks // # We don't reset tmp_value here because _on_change might put callbacks
// # in the CallAfter queue, and we want the tmp value to be available from // # in the CallAfter queue, and we want the tmp value to be available from
// # them as well. // # them as well.

View file

@ -29,8 +29,8 @@ namespace Slic3r { namespace GUI {
class Field; class Field;
using t_field = std::unique_ptr<Field>; using t_field = std::unique_ptr<Field>;
using t_kill_focus = std::function<void()>; using t_kill_focus = std::function<void(const std::string&)>;
using t_change = std::function<void(t_config_option_key, const boost::any&)>; using t_change = std::function<void(const t_config_option_key&, const boost::any&)>;
using t_back_to_init = std::function<void(const std::string&)>; using t_back_to_init = std::function<void(const std::string&)>;
wxString double_to_string(double const value, const int max_precision = 4); wxString double_to_string(double const value, const int max_precision = 4);
@ -139,10 +139,9 @@ public:
/// Factory method for generating new derived classes. /// Factory method for generating new derived classes.
template<class T> template<class T>
static t_field Create(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id, const bool process_enter = false)// interface for creating shared objects static t_field Create(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id)// interface for creating shared objects
{ {
auto p = Slic3r::make_unique<T>(parent, opt, id); auto p = Slic3r::make_unique<T>(parent, opt, id);
p->m_process_enter = process_enter;
p->PostInitialize(); p->PostInitialize();
return std::move(p); //!p; return std::move(p); //!p;
} }
@ -223,9 +222,6 @@ protected:
// current value // current value
boost::any m_value; boost::any m_value;
//this variable shows a mode of a call of the on_change function
bool m_process_enter { false };
friend class OptionsGroup; friend class OptionsGroup;
}; };
@ -265,7 +261,7 @@ public:
} }
boost::any& get_value() override; boost::any& get_value() override;
bool is_defined_input_value(); bool is_defined_input_value() const ;
virtual void enable(); virtual void enable();
virtual void disable(); virtual void disable();

View file

@ -453,7 +453,6 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
obj->SetText(wxString::Format("%d", m_objects_model->GetVolumeIdByItem(item))); obj->SetText(wxString::Format("%d", m_objects_model->GetVolumeIdByItem(item)));
event.SetDataObject(obj); event.SetDataObject(obj);
event.SetDragFlags(/*wxDrag_AllowMove*/wxDrag_DefaultMove); // allows both copy and move; event.SetDragFlags(/*wxDrag_AllowMove*/wxDrag_DefaultMove); // allows both copy and move;
printf("BeginDrag\n");
} }
void ObjectList::OnDropPossible(wxDataViewEvent &event) void ObjectList::OnDropPossible(wxDataViewEvent &event)
@ -464,7 +463,6 @@ void ObjectList::OnDropPossible(wxDataViewEvent &event)
if (event.GetDataFormat() != wxDF_UNICODETEXT || item.IsOk() && if (event.GetDataFormat() != wxDF_UNICODETEXT || item.IsOk() &&
(m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->GetItemType(item) != itVolume)) (m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->GetItemType(item) != itVolume))
event.Veto(); event.Veto();
printf("DropPossible\n");
} }
void ObjectList::OnDrop(wxDataViewEvent &event) void ObjectList::OnDrop(wxDataViewEvent &event)
@ -477,13 +475,14 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
event.Veto(); event.Veto();
return; return;
} }
printf("Drop\n");
wxTextDataObject obj; wxTextDataObject obj;
obj.SetData(wxDF_UNICODETEXT, event.GetDataSize(), event.GetDataBuffer()); obj.SetData(wxDF_UNICODETEXT, event.GetDataSize(), event.GetDataBuffer());
printf("Drop\n");
int from_volume_id = std::stoi(obj.GetText().ToStdString()); int from_volume_id = std::stoi(obj.GetText().ToStdString());
int to_volume_id = m_objects_model->GetVolumeIdByItem(item); int to_volume_id = m_objects_model->GetVolumeIdByItem(item);
printf("from %d to %d\n", from_volume_id, to_volume_id);
#ifdef __WXGTK__ #ifdef __WXGTK__
/* Under GTK, DnD moves an item between another two items. /* Under GTK, DnD moves an item between another two items.
@ -498,10 +497,12 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
int cnt = 0; int cnt = 0;
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++) for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++)
std::swap(volumes[id], volumes[id + delta]); std::swap(volumes[id], volumes[id + delta]);
printf("Volumes are swapped\n");
select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id,
m_objects_model->GetParent(item))); m_objects_model->GetParent(item)));
printf("ItemChildren are Reorganized\n");
m_parts_changed = true; m_parts_changed = true;
parts_changed(m_selected_object_id); parts_changed(m_selected_object_id);

View file

@ -21,9 +21,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
m_og->set_name(_(L("Object Manipulation"))); m_og->set_name(_(L("Object Manipulation")));
m_og->label_width = 100; m_og->label_width = 100;
m_og->set_grid_vgap(5); m_og->set_grid_vgap(5);
m_og->set_process_enter(); // We need to update new values only after press ENTER
m_og->m_on_change = [this](t_config_option_key opt_key, boost::any value) { m_og->m_on_change = [this](const std::string& opt_key, const boost::any& value) {
std::vector<std::string> axes{ "_x", "_y", "_z" }; std::vector<std::string> axes{ "_x", "_y", "_z" };
if (opt_key == "scale_unit") { if (opt_key == "scale_unit") {
@ -54,6 +53,24 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
change_scale_value(new_value); change_scale_value(new_value);
}; };
m_og->m_fill_empty_value = [this](const std::string& opt_key)
{
if (opt_key == "scale_unit")
return;
std::string param;
std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param));
if (param == "position") {
int axis = opt_key.back() == 'x' ? 0 :
opt_key.back() == 'y' ? 1 : 2;
m_og->set_value(opt_key, double_to_string(cache_position(axis)));
return;
}
m_og->set_value(opt_key, double_to_string(0.0));
};
ConfigOptionDef def; ConfigOptionDef def;
// Objects(sub-objects) name // Objects(sub-objects) name

View file

@ -17,7 +17,7 @@ protected:
wxWindow* m_parent; wxWindow* m_parent;
public: public:
OG_Settings(wxWindow* parent, const bool staticbox); OG_Settings(wxWindow* parent, const bool staticbox);
~OG_Settings() {} virtual ~OG_Settings() {}
virtual bool IsShown(); virtual bool IsShown();
virtual void Show(const bool show); virtual void Show(const bool show);

View file

@ -44,7 +44,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
case coPercents: case coPercents:
case coString: case coString:
case coStrings: case coStrings:
m_fields.emplace(id, std::move(TextCtrl::Create<TextCtrl>(parent(), opt, id, process_enter))); m_fields.emplace(id, std::move(TextCtrl::Create<TextCtrl>(parent(), opt, id)));
break; break;
case coBool: case coBool:
case coBools: case coBools:
@ -67,16 +67,16 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
} }
// Grab a reference to fields for convenience // Grab a reference to fields for convenience
const t_field& field = m_fields[id]; const t_field& field = m_fields[id];
field->m_on_change = [this](std::string opt_id, boost::any value) { field->m_on_change = [this](const std::string& opt_id, const boost::any& value) {
//! This function will be called from Field. //! This function will be called from Field.
//! Call OptionGroup._on_change(...) //! Call OptionGroup._on_change(...)
if (!m_disabled) if (!m_disabled)
this->on_change_OG(opt_id, value); this->on_change_OG(opt_id, value);
}; };
field->m_on_kill_focus = [this]() { field->m_on_kill_focus = [this](const std::string& opt_id) {
//! This function will be called from Field. //! This function will be called from Field.
if (!m_disabled) if (!m_disabled)
this->on_kill_focus(); this->on_kill_focus(opt_id);
}; };
field->m_parent = parent(); field->m_parent = parent();
@ -378,6 +378,15 @@ void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config,
on_change_OG(opt_key, get_value(opt_key)); on_change_OG(opt_key, get_value(opt_key));
} }
void ConfigOptionsGroup::on_kill_focus(const std::string& opt_key)
{
if (m_fill_empty_value) {
m_fill_empty_value(opt_key);
return;
}
reload_config();
}
void ConfigOptionsGroup::reload_config() { void ConfigOptionsGroup::reload_config() {
for (t_opt_map::iterator it = m_opt_map.begin(); it != m_opt_map.end(); ++it) { for (t_opt_map::iterator it = m_opt_map.begin(); it != m_opt_map.end(); ++it) {
auto opt_id = it->first; auto opt_id = it->first;

View file

@ -85,7 +85,8 @@ public:
size_t label_width {200}; size_t label_width {200};
wxSizer* sizer {nullptr}; wxSizer* sizer {nullptr};
column_t extra_column {nullptr}; column_t extra_column {nullptr};
t_change m_on_change {nullptr}; t_change m_on_change { nullptr };
t_kill_focus m_fill_empty_value { nullptr };
std::function<DynamicPrintConfig()> m_get_initial_config{ nullptr }; std::function<DynamicPrintConfig()> m_get_initial_config{ nullptr };
std::function<DynamicPrintConfig()> m_get_sys_config{ nullptr }; std::function<DynamicPrintConfig()> m_get_sys_config{ nullptr };
std::function<bool()> have_sys_config{ nullptr }; std::function<bool()> have_sys_config{ nullptr };
@ -94,8 +95,6 @@ public:
wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
int sidetext_width{ -1 }; int sidetext_width{ -1 };
bool process_enter { false };
/// Returns a copy of the pointer of the parent wxWindow. /// Returns a copy of the pointer of the parent wxWindow.
/// Accessor function is because users are not allowed to change the parent /// Accessor function is because users are not allowed to change the parent
/// but defining it as const means a lot of const_casts to deal with wx functions. /// but defining it as const means a lot of const_casts to deal with wx functions.
@ -154,11 +153,6 @@ public:
m_show_modified_btns = show; m_show_modified_btns = show;
} }
// The controls inside this option group will generate the event wxEVT_TEXT_ENTER
void set_process_enter() {
process_enter = true;
}
OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false, OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false,
column_t extra_clmn = nullptr) : column_t extra_clmn = nullptr) :
m_parent(_parent), title(title), m_parent(_parent), title(title),
@ -215,7 +209,7 @@ protected:
const t_field& build_field(const Option& opt, wxStaticText* label = nullptr); const t_field& build_field(const Option& opt, wxStaticText* label = nullptr);
void add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& field); void add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& field);
virtual void on_kill_focus () {}; virtual void on_kill_focus(const std::string& opt_key) {};
virtual void on_change_OG(const t_config_option_key& opt_id, const boost::any& value); virtual void on_change_OG(const t_config_option_key& opt_id, const boost::any& value);
virtual void back_to_initial_value(const std::string& opt_key) {} virtual void back_to_initial_value(const std::string& opt_key) {}
virtual void back_to_sys_value(const std::string& opt_key) {} virtual void back_to_sys_value(const std::string& opt_key) {}
@ -251,7 +245,7 @@ public:
void back_to_initial_value(const std::string& opt_key) override; void back_to_initial_value(const std::string& opt_key) override;
void back_to_sys_value(const std::string& opt_key) override; void back_to_sys_value(const std::string& opt_key) override;
void back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key); void back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key);
void on_kill_focus() override{ reload_config();} void on_kill_focus(const std::string& opt_key) override;// { reload_config(); }
void reload_config(); void reload_config();
// return value shows visibility : false => all options are hidden // return value shows visibility : false => all options are hidden
void Hide(); void Hide();

View file

@ -270,7 +270,7 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str
auto panel = this; auto panel = this;
#endif #endif
PageShp page(new Page(panel, title, icon_idx)); PageShp page(new Page(panel, title, icon_idx));
page->SetScrollbars(1, 1, 1, 1); page->SetScrollbars(1, 1, 1, 2);
page->Hide(); page->Hide();
m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5); m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5);