diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 642a866f3..c83c7248b 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -87,6 +87,8 @@ protected: void on_set_focus(wxEvent& event); /// Call the attached on_change method. void on_change_field(); + +public: /// Call the attached m_back_to_initial_value method. void on_back_to_initial_value(); /// Call the attached m_back_to_sys_value method. diff --git a/src/slic3r/GUI/OG_CustomCtrl.cpp b/src/slic3r/GUI/OG_CustomCtrl.cpp index bbdc6869f..443d6c148 100644 --- a/src/slic3r/GUI/OG_CustomCtrl.cpp +++ b/src/slic3r/GUI/OG_CustomCtrl.cpp @@ -39,12 +39,12 @@ OG_CustomCtrl::OG_CustomCtrl( wxWindow* parent, this->Bind(wxEVT_PAINT, &OG_CustomCtrl::OnPaint, this); this->Bind(wxEVT_MOTION, &OG_CustomCtrl::OnMotion, this); this->Bind(wxEVT_LEFT_DOWN, &OG_CustomCtrl::OnLeftDown, this); - this->Bind(wxEVT_LEFT_UP, &OG_CustomCtrl::OnLeftUp, this); } void OG_CustomCtrl::init_ctrl_lines() { - for (const Line& line : opt_group->get_lines()) + const std::vector<Line>& og_lines = opt_group->get_lines(); + for (const Line& line : og_lines) { if (line.full_width && ( // description line @@ -64,13 +64,13 @@ void OG_CustomCtrl::init_ctrl_lines() line.get_extra_widgets().size() == 0) { height = m_bmp_blinking_sz.GetHeight() + m_v_gap; - ctrl_lines.emplace_back(CtrlLine{ height, this, line, true }); + ctrl_lines.emplace_back(CtrlLine(height, this, line, true)); } else if (opt_group->label_width != 0 && !line.label.IsEmpty()) { wxSize label_sz = GetTextExtent(line.label); height = label_sz.y * (label_sz.GetWidth() > int(opt_group->label_width * m_em_unit) ? 2 : 1) + m_v_gap; - ctrl_lines.emplace_back(CtrlLine{ height, this, line }); + ctrl_lines.emplace_back(CtrlLine(height, this, line)); } else int i = 0; @@ -106,10 +106,12 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/) if (opt_group->label_width != 0 && !label.IsEmpty()) h_pos += opt_group->label_width * m_em_unit + m_h_gap; - if (line.widget) - break; + int blinking_button_width = m_bmp_blinking_sz.GetWidth() + m_h_gap; - int action_buttons_width = 3 * (m_bmp_blinking_sz.GetWidth() + m_h_gap); + if (line.widget) { + h_pos += blinking_button_width; + break; + } // If we have a single option with no sidetext const std::vector<Option>& option_set = line.get_options(); @@ -117,7 +119,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/) option_set.front().opt.label.empty() && option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) { - h_pos += action_buttons_width; + h_pos += 3 * blinking_button_width; break; } @@ -135,7 +137,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/) dc.SetFont(m_font); h_pos += dc.GetMultiLineTextExtent(label).x + m_h_gap; } - h_pos += action_buttons_width; + h_pos += 3 * blinking_button_width; if (field == field_in) break; @@ -169,11 +171,15 @@ void OG_CustomCtrl::OnPaint(wxPaintEvent&) SetBackgroundColour(GetParent()->GetBackgroundColour()); #endif // _WIN32 + // case, when custom controll is destroyed but doesn't deleted from the evet loop + if(!this->opt_group->custom_ctrl) + return; + wxPaintDC dc(this); dc.SetFont(m_font); wxCoord v_pos = 0; - for (auto line : ctrl_lines) { + for (CtrlLine& line : ctrl_lines) { if (!line.is_visible) continue; line.render(dc, v_pos); @@ -181,11 +187,41 @@ void OG_CustomCtrl::OnPaint(wxPaintEvent&) } } +static bool is_point_in_rect(const wxPoint& pt, const wxRect& rect) +{ + return rect.GetLeft() <= pt.x && pt.x <= rect.GetRight() && + rect.GetTop() <= pt.y && pt.y <= rect.GetBottom(); +} + void OG_CustomCtrl::OnMotion(wxMouseEvent& event) { - bool action = false; - const wxPoint pos = event.GetLogicalPosition(wxClientDC(this)); + wxString tooltip; + + for (const CtrlLine& line : ctrl_lines) { + for (size_t opt_idx = 0; opt_idx < line.rects_undo_icon.size(); opt_idx++) + if (is_point_in_rect(pos, line.rects_undo_icon[opt_idx])) { + const std::vector<Option>& option_set = line.og_line.get_options(); + Field* field = opt_group->get_field(option_set[opt_idx].opt_id); + if (field) + tooltip = *field->undo_tooltip(); + break; + } + for (size_t opt_idx = 0; opt_idx < line.rects_undo_to_sys_icon.size(); opt_idx++) + if (is_point_in_rect(pos, line.rects_undo_to_sys_icon[opt_idx])) { + const std::vector<Option>& option_set = line.og_line.get_options(); + Field* field = opt_group->get_field(option_set[opt_idx].opt_id); + if (field) + tooltip = *field->undo_to_sys_tooltip(); + break; + } + if (!tooltip.IsEmpty()) + break; + } + + // Set tooltips with information for each icon + this->SetToolTip(tooltip); + Refresh(); Update(); event.Skip(); @@ -193,20 +229,29 @@ void OG_CustomCtrl::OnMotion(wxMouseEvent& event) void OG_CustomCtrl::OnLeftDown(wxMouseEvent& event) { - if (HasCapture()) - return; - this->CaptureMouse(); + const wxPoint pos = event.GetLogicalPosition(wxClientDC(this)); - event.Skip(); -} + for (const CtrlLine& line : ctrl_lines) { + for (size_t opt_idx = 0; opt_idx < line.rects_undo_icon.size(); opt_idx++) + if (is_point_in_rect(pos, line.rects_undo_icon[opt_idx])) { + const std::vector<Option>& option_set = line.og_line.get_options(); + Field* field = opt_group->get_field(option_set[opt_idx].opt_id); + if (field) + field->on_back_to_initial_value(); + event.Skip(); + return; + } + for (size_t opt_idx = 0; opt_idx < line.rects_undo_to_sys_icon.size(); opt_idx++) + if (is_point_in_rect(pos, line.rects_undo_to_sys_icon[opt_idx])) { + const std::vector<Option>& option_set = line.og_line.get_options(); + Field* field = opt_group->get_field(option_set[opt_idx].opt_id); + if (field) + field->on_back_to_sys_value(); + event.Skip(); + return; + } + } -void OG_CustomCtrl::OnLeftUp(wxMouseEvent& event) -{ - if (HasCapture()) - return; - this->CaptureMouse(); - - event.Skip(); } bool OG_CustomCtrl::update_visibility(ConfigOptionMode mode) @@ -275,6 +320,27 @@ void OG_CustomCtrl::sys_color_changed() msw_rescale(); } +OG_CustomCtrl::CtrlLine::CtrlLine( wxCoord height, + OG_CustomCtrl* ctrl, + const Line& og_line, + bool draw_just_act_buttons /* = false*/): + height(height), + ctrl(ctrl), + og_line(og_line), + draw_just_act_buttons(draw_just_act_buttons) +{ + if (og_line.widget) { + rects_blinking.emplace_back(wxRect()); + return; + } + + for (size_t i = 0; i < og_line.get_options().size(); i++) { + rects_blinking.emplace_back(wxRect()); + rects_undo_icon.emplace_back(wxRect()); + rects_undo_to_sys_icon.emplace_back(wxRect()); + } +} + void OG_CustomCtrl::CtrlLine::correct_items_positions() { if (draw_just_act_buttons || !is_visible) @@ -377,9 +443,11 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos) h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label + ":", text_clr, ctrl->opt_group->label_width * ctrl->m_em_unit); } - // If there's a widget, build it and add the result to the sizer. - if (og_line.widget != nullptr) + // If there's a widget, build it and set result to the correct position. + if (og_line.widget != nullptr) { + draw_blinking_bmp(dc, wxPoint(h_pos, v_pos)); return; + } // If we're here, we have more than one option or a single option with sidetext // so we need a horizontal sizer to arrange these things @@ -389,11 +457,12 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos) option_set.front().opt.label.empty() && option_set.front().side_widget == nullptr && og_line.get_extra_widgets().size() == 0) { - if (field) + if (field && field->undo_to_sys_bitmap()) draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp()); return; } + size_t bmp_rect_id = 0; for (auto opt : option_set) { field = ctrl->opt_group->get_field(opt.opt_id); ConfigOptionDef option = opt.opt; @@ -407,8 +476,8 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos) h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, field ? field->label_color() : nullptr, ctrl->opt_group->sublabel_width * ctrl->m_em_unit); } - if (field) { - h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp()); + if (field && field->undo_to_sys_bitmap()) { + h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), bmp_rect_id++); if (field->getSizer()) { auto children = field->getSizer()->GetChildren(); @@ -490,28 +559,38 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxStr return pos.x + width + ctrl->m_h_gap; } -wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo) +wxPoint OG_CustomCtrl::CtrlLine::draw_blinking_bmp(wxDC& dc, wxPoint pos, size_t rect_id) { - wxBitmap bmp_blinking = create_scaled_bitmap("search_blink", ctrl); +// wxBitmap bmp_blinking = create_scaled_bitmap("search_blink", ctrl); + wxBitmap bmp_blinking = create_scaled_bitmap("empty", ctrl); wxCoord h_pos = pos.x; - wxCoord pos_y = pos.y + lround((height - bmp_blinking.GetHeight()) / 2); + wxCoord v_pos = pos.y + lround((height - bmp_blinking.GetHeight()) / 2); - dc.DrawBitmap(bmp_blinking, h_pos, pos_y); + dc.DrawBitmap(bmp_blinking, h_pos, v_pos); int bmp_dim = bmp_blinking.GetWidth(); - m_rect_blinking = wxRect(h_pos, pos_y, bmp_dim, bmp_dim); + rects_blinking[rect_id] = wxRect(h_pos, v_pos, bmp_dim, bmp_dim); h_pos += bmp_dim + ctrl->m_h_gap; - dc.DrawBitmap(bmp_undo_to_sys, h_pos, pos_y); + return wxPoint(h_pos, v_pos); +} - bmp_dim = bmp_undo_to_sys.GetWidth(); - m_rect_undo_to_sys_icon = wxRect(h_pos, pos_y, bmp_dim, bmp_dim); +wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, size_t rect_id) +{ + pos = draw_blinking_bmp(dc, pos, rect_id); + wxCoord h_pos = pos.x; + wxCoord v_pos = pos.y; + + dc.DrawBitmap(bmp_undo_to_sys, h_pos, v_pos); + + int bmp_dim = bmp_undo_to_sys.GetWidth(); + rects_undo_to_sys_icon[rect_id] = wxRect(h_pos, v_pos, bmp_dim, bmp_dim); h_pos += bmp_dim + ctrl->m_h_gap; - dc.DrawBitmap(bmp_undo, h_pos, pos_y); + dc.DrawBitmap(bmp_undo, h_pos, v_pos); bmp_dim = bmp_undo.GetWidth(); - m_rect_undo_icon = wxRect(h_pos, pos_y, bmp_dim, bmp_dim); + rects_undo_icon[rect_id] = wxRect(h_pos, v_pos, bmp_dim, bmp_dim); h_pos += bmp_dim + ctrl->m_h_gap; diff --git a/src/slic3r/GUI/OG_CustomCtrl.hpp b/src/slic3r/GUI/OG_CustomCtrl.hpp index 9f9ee0300..dcd43fe20 100644 --- a/src/slic3r/GUI/OG_CustomCtrl.hpp +++ b/src/slic3r/GUI/OG_CustomCtrl.hpp @@ -43,10 +43,10 @@ class OG_CustomCtrl :public wxControl bool draw_just_act_buttons { false }; bool is_visible { true }; - wxRect m_rect_blinking; - wxRect m_rect_undo_icon; - wxRect m_rect_undo_to_sys_icon; - + CtrlLine( wxCoord height, + OG_CustomCtrl* ctrl, + const Line& og_line, + bool draw_just_act_buttons = false); ~CtrlLine() { ctrl = nullptr; } void correct_items_positions(); @@ -56,7 +56,12 @@ class OG_CustomCtrl :public wxControl void render(wxDC& dc, wxCoord v_pos); wxCoord draw_mode_bmp(wxDC& dc, wxCoord v_pos); wxCoord draw_text (wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width); - wxCoord draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo); + wxPoint draw_blinking_bmp(wxDC& dc, wxPoint pos, size_t rect_id = 0); + wxCoord draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, size_t rect_id = 0); + + std::vector<wxRect> rects_blinking; + std::vector<wxRect> rects_undo_icon; + std::vector<wxRect> rects_undo_to_sys_icon; }; std::vector<CtrlLine> ctrl_lines; @@ -73,7 +78,6 @@ public: void OnPaint(wxPaintEvent&); void OnMotion(wxMouseEvent& event); void OnLeftDown(wxMouseEvent& event); - void OnLeftUp(wxMouseEvent& event); void init_ctrl_lines(); bool update_visibility(ConfigOptionMode mode); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 7a07879dc..4044e80e7 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -428,7 +428,7 @@ bool OptionsGroup::activate(std::function<void()> throw_if_canceled) return true; } // delete all controls from the option group -void OptionsGroup::clear() +void OptionsGroup::clear(bool destroy_custom_ctrl) { if (!sizer) return; @@ -460,7 +460,10 @@ void OptionsGroup::clear() if (win) win = nullptr; } - custom_ctrl = nullptr; + if (destroy_custom_ctrl) + custom_ctrl->Destroy(); + else + custom_ctrl = nullptr; } m_extra_column_item_ptrs.clear(); @@ -736,6 +739,12 @@ void ConfigOptionsGroup::sys_color_changed() field.second->sys_color_changed(); } +void ConfigOptionsGroup::refresh() +{ + if (custom_ctrl) + custom_ctrl->Refresh(); +} + boost::any ConfigOptionsGroup::config_value(const std::string& opt_key, int opt_index, bool deserialize) { if (deserialize) { diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index c85e78a77..02b641ab5 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -135,7 +135,7 @@ public: // create all controls for the option group from the m_lines bool activate(std::function<void()> throw_if_canceled = [](){}); // delete all controls from the option group - void clear(); + void clear(bool destroy_custom_ctrl = false); Line create_single_option_line(const Option& option) const; void append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); } @@ -191,6 +191,7 @@ public: OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false, column_t extra_clmn = nullptr); + ~OptionsGroup() { clear(true); } wxGridSizer* get_grid_sizer() { return m_grid_sizer; } @@ -284,6 +285,7 @@ public: bool update_visibility(ConfigOptionMode mode); void msw_rescale(); void sys_color_changed(); + void refresh(); boost::any config_value(const std::string& opt_key, int opt_index, bool deserialize); // return option value from config boost::any get_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int opt_index = -1); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 7660307ae..78b035c28 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -593,6 +593,9 @@ void Tab::decorate() field->set_undo_to_sys_tooltip(sys_tt); field->set_label_colour(color); } + + if (m_active_page) + m_active_page->refresh(); } // Update UI according to changes @@ -3533,10 +3536,10 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true); deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - BlinkingBitmap* bbmp = new BlinkingBitmap(parent); +// BlinkingBitmap* bbmp = new BlinkingBitmap(parent); auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(bbmp, 0, wxALIGN_CENTER_VERTICAL); +// sizer->Add(bbmp, 0, wxALIGN_CENTER_VERTICAL); sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL); sizer->Add((deps.btn), 0, wxALIGN_CENTER_VERTICAL); @@ -3599,7 +3602,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep // fill m_blinking_ikons map with options { - m_blinking_ikons[deps.key_list] = bbmp; + // m_blinking_ikons[deps.key_list] = bbmp; } return sizer; @@ -3612,10 +3615,10 @@ wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent) wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true); btn->SetFont(wxGetApp().normal_font()); - BlinkingBitmap* bbmp = new BlinkingBitmap(parent); +// BlinkingBitmap* bbmp = new BlinkingBitmap(parent); auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(bbmp, 0, wxALIGN_CENTER_VERTICAL); +// sizer->Add(bbmp, 0, wxALIGN_CENTER_VERTICAL); sizer->Add(btn, 0, wxALIGN_CENTER_VERTICAL); btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) @@ -3649,8 +3652,8 @@ wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent) // fill m_blinking_ikons map with options { - for (const std::string opt : {"bed_shape", "bed_custom_texture", "bed_custom_model"}) - m_blinking_ikons[opt] = bbmp; + //for (const std::string opt : {"bed_shape", "bed_custom_texture", "bed_custom_model"}) + // m_blinking_ikons[opt] = bbmp; } return sizer; @@ -3824,6 +3827,12 @@ void Page::sys_color_changed() group->sys_color_changed(); } +void Page::refresh() +{ + for (auto group : m_optgroups) + group->refresh(); +} + Field* Page::get_field(const t_config_option_key& opt_key, int opt_index /*= -1*/) const { Field* field = nullptr; diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 0fa4f768d..0ebac4f7c 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -77,6 +77,7 @@ public: void clear(); void msw_rescale(); void sys_color_changed(); + void refresh(); Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; bool set_value(const t_config_option_key& opt_key, const boost::any& value); ConfigOptionsGroupShp new_optgroup(const wxString& title, int noncommon_label_width = -1);