diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 14f409698..29218eaf6 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -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(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. diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index aef2094a7..66a71b34d 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -29,8 +29,8 @@ namespace Slic3r { namespace GUI { class Field; using t_field = std::unique_ptr; -using t_kill_focus = std::function; -using t_change = std::function; +using t_kill_focus = std::function; +using t_change = std::function; using t_back_to_init = std::function; 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 - 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(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(); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 85236b2a1..ba98573bf 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -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); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 28d709ef7..d12aabf9e 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -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 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 diff --git a/src/slic3r/GUI/GUI_ObjectSettings.hpp b/src/slic3r/GUI/GUI_ObjectSettings.hpp index 7b58d4c4e..19140efe3 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.hpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.hpp @@ -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); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index be9a4e9cd..512bcb4ac 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -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(parent(), opt, id, process_enter))); + m_fields.emplace(id, std::move(TextCtrl::Create(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; diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index dd135636d..e80324628 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -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 m_get_initial_config{ nullptr }; std::function m_get_sys_config{ nullptr }; std::function 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(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 9a5c960bb..fa39ac240 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -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);