Update value inside TextCtrl & SpinCtrl after wxEVT_KILL_FOCES instead of wxEVT_TEXT (or wxEVT_TEXT_ENTER)
This commit is contained in:
parent
c4e334f863
commit
d7bc1410ee
8 changed files with 68 additions and 47 deletions
|
@ -74,7 +74,7 @@ void Field::on_kill_focus(wxEvent& event)
|
|||
event.Skip();
|
||||
// call the registered function if it is available
|
||||
if (m_on_kill_focus!=nullptr)
|
||||
m_on_kill_focus();
|
||||
m_on_kill_focus(m_opt_id);
|
||||
}
|
||||
|
||||
void Field::on_change_field()
|
||||
|
@ -125,9 +125,9 @@ void Field::get_value_by_opt_type(wxString& str)
|
|||
case coPercents:
|
||||
case coFloats:
|
||||
case coFloat:{
|
||||
if (m_opt.type == coPercent && str.Last() == '%')
|
||||
if (m_opt.type == coPercent && !str.IsEmpty() && str.Last() == '%')
|
||||
str.RemoveLast();
|
||||
else if (str.Last() == '%') {
|
||||
else if (!str.IsEmpty() && str.Last() == '%') {
|
||||
wxString label = m_Label->GetLabel();
|
||||
if (label.Last() == '\n') 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)
|
||||
return false;
|
||||
|
@ -216,7 +216,7 @@ void TextCtrl::BUILD() {
|
|||
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);
|
||||
|
||||
temp->SetToolTip(get_tooltip_text(text_value));
|
||||
|
@ -240,17 +240,13 @@ void TextCtrl::BUILD() {
|
|||
e.Skip();
|
||||
temp->GetToolTip()->Enable(true);
|
||||
#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);
|
||||
}), 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)
|
||||
{
|
||||
#ifdef __WXGTK__
|
||||
|
@ -267,8 +263,7 @@ void TextCtrl::BUILD() {
|
|||
temp->Bind(wxEVT_KEY_DOWN, &TextCtrl::change_field_value, this);
|
||||
temp->Bind(wxEVT_KEY_UP, &TextCtrl::change_field_value, this);
|
||||
#endif //__WXGTK__
|
||||
}
|
||||
|
||||
*/
|
||||
// select all text using Ctrl+A
|
||||
temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event)
|
||||
{
|
||||
|
@ -371,7 +366,15 @@ void SpinCtrl::BUILD() {
|
|||
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_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)
|
||||
{
|
||||
// # 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();
|
||||
if (is_matched(value, "^\\d+$"))
|
||||
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
|
||||
// # in the CallAfter queue, and we want the tmp value to be available from
|
||||
// # them as well.
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace Slic3r { namespace GUI {
|
|||
|
||||
class Field;
|
||||
using t_field = std::unique_ptr<Field>;
|
||||
using t_kill_focus = std::function<void()>;
|
||||
using t_change = std::function<void(t_config_option_key, const boost::any&)>;
|
||||
using t_kill_focus = std::function<void(const std::string&)>;
|
||||
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&)>;
|
||||
|
||||
wxString double_to_string(double const value, const int max_precision = 4);
|
||||
|
@ -139,10 +139,9 @@ public:
|
|||
|
||||
/// Factory method for generating new derived classes.
|
||||
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);
|
||||
p->m_process_enter = process_enter;
|
||||
p->PostInitialize();
|
||||
return std::move(p); //!p;
|
||||
}
|
||||
|
@ -223,9 +222,6 @@ protected:
|
|||
// current 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;
|
||||
};
|
||||
|
||||
|
@ -265,7 +261,7 @@ public:
|
|||
}
|
||||
|
||||
boost::any& get_value() override;
|
||||
bool is_defined_input_value();
|
||||
bool is_defined_input_value() const ;
|
||||
|
||||
virtual void enable();
|
||||
virtual void disable();
|
||||
|
|
|
@ -453,7 +453,6 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
|
|||
obj->SetText(wxString::Format("%d", m_objects_model->GetVolumeIdByItem(item)));
|
||||
event.SetDataObject(obj);
|
||||
event.SetDragFlags(/*wxDrag_AllowMove*/wxDrag_DefaultMove); // allows both copy and move;
|
||||
printf("BeginDrag\n");
|
||||
}
|
||||
|
||||
void ObjectList::OnDropPossible(wxDataViewEvent &event)
|
||||
|
@ -464,7 +463,6 @@ void ObjectList::OnDropPossible(wxDataViewEvent &event)
|
|||
if (event.GetDataFormat() != wxDF_UNICODETEXT || item.IsOk() &&
|
||||
(m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->GetItemType(item) != itVolume))
|
||||
event.Veto();
|
||||
printf("DropPossible\n");
|
||||
}
|
||||
|
||||
void ObjectList::OnDrop(wxDataViewEvent &event)
|
||||
|
@ -477,13 +475,14 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
|||
event.Veto();
|
||||
return;
|
||||
}
|
||||
printf("Drop\n");
|
||||
|
||||
wxTextDataObject obj;
|
||||
obj.SetData(wxDF_UNICODETEXT, event.GetDataSize(), event.GetDataBuffer());
|
||||
printf("Drop\n");
|
||||
|
||||
int from_volume_id = std::stoi(obj.GetText().ToStdString());
|
||||
int to_volume_id = m_objects_model->GetVolumeIdByItem(item);
|
||||
printf("from %d to %d\n", from_volume_id, to_volume_id);
|
||||
|
||||
#ifdef __WXGTK__
|
||||
/* Under GTK, DnD moves an item between another two items.
|
||||
|
@ -498,10 +497,12 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
|||
int cnt = 0;
|
||||
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++)
|
||||
std::swap(volumes[id], volumes[id + delta]);
|
||||
printf("Volumes are swapped\n");
|
||||
|
||||
select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id,
|
||||
m_objects_model->GetParent(item)));
|
||||
|
||||
printf("ItemChildren are Reorganized\n");
|
||||
m_parts_changed = true;
|
||||
parts_changed(m_selected_object_id);
|
||||
|
||||
|
|
|
@ -21,9 +21,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
m_og->set_name(_(L("Object Manipulation")));
|
||||
m_og->label_width = 100;
|
||||
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" };
|
||||
|
||||
if (opt_key == "scale_unit") {
|
||||
|
@ -54,6 +53,24 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
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;
|
||||
|
||||
// Objects(sub-objects) name
|
||||
|
|
|
@ -17,7 +17,7 @@ protected:
|
|||
wxWindow* m_parent;
|
||||
public:
|
||||
OG_Settings(wxWindow* parent, const bool staticbox);
|
||||
~OG_Settings() {}
|
||||
virtual ~OG_Settings() {}
|
||||
|
||||
virtual bool IsShown();
|
||||
virtual void Show(const bool show);
|
||||
|
|
|
@ -44,7 +44,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
|
|||
case coPercents:
|
||||
case coString:
|
||||
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;
|
||||
case coBool:
|
||||
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
|
||||
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.
|
||||
//! Call OptionGroup._on_change(...)
|
||||
if (!m_disabled)
|
||||
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.
|
||||
if (!m_disabled)
|
||||
this->on_kill_focus();
|
||||
this->on_kill_focus(opt_id);
|
||||
};
|
||||
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));
|
||||
}
|
||||
|
||||
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() {
|
||||
for (t_opt_map::iterator it = m_opt_map.begin(); it != m_opt_map.end(); ++it) {
|
||||
auto opt_id = it->first;
|
||||
|
|
|
@ -85,7 +85,8 @@ public:
|
|||
size_t label_width {200};
|
||||
wxSizer* sizer {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_sys_config{ nullptr };
|
||||
std::function<bool()> have_sys_config{ nullptr };
|
||||
|
@ -94,8 +95,6 @@ public:
|
|||
wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
|
||||
int sidetext_width{ -1 };
|
||||
|
||||
bool process_enter { false };
|
||||
|
||||
/// Returns a copy of the pointer of the parent wxWindow.
|
||||
/// 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.
|
||||
|
@ -154,11 +153,6 @@ public:
|
|||
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,
|
||||
column_t extra_clmn = nullptr) :
|
||||
m_parent(_parent), title(title),
|
||||
|
@ -215,7 +209,7 @@ protected:
|
|||
const t_field& build_field(const Option& opt, wxStaticText* label = nullptr);
|
||||
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 back_to_initial_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_sys_value(const std::string& opt_key) override;
|
||||
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();
|
||||
// return value shows visibility : false => all options are hidden
|
||||
void Hide();
|
||||
|
|
|
@ -270,7 +270,7 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str
|
|||
auto panel = this;
|
||||
#endif
|
||||
PageShp page(new Page(panel, title, icon_idx));
|
||||
page->SetScrollbars(1, 1, 1, 1);
|
||||
page->SetScrollbars(1, 1, 1, 2);
|
||||
page->Hide();
|
||||
m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5);
|
||||
|
||||
|
|
Loading…
Reference in a new issue