From 7db83d58f0af11efaacdc732641531dee739563b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 31 May 2023 11:17:06 +0200 Subject: [PATCH] Editing of Custom G-code: Prepared UI part on SettingsTabs * Added "Edit" button for all custom G-codes --- src/slic3r/GUI/Field.cpp | 6 +++++ src/slic3r/GUI/Field.hpp | 41 +++++++++++++++++++++++++++++ src/slic3r/GUI/OG_CustomCtrl.cpp | 44 ++++++++++++++++++++++++++------ src/slic3r/GUI/OG_CustomCtrl.hpp | 4 ++- src/slic3r/GUI/OptionsGroup.cpp | 8 ++++++ src/slic3r/GUI/OptionsGroup.hpp | 2 ++ src/slic3r/GUI/Tab.cpp | 29 +++++++++++++++++++++ src/slic3r/GUI/Tab.hpp | 3 +++ 8 files changed, 128 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index bbc2b04dd20..a2f72eaeade 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -245,6 +245,12 @@ void Field::on_back_to_sys_value() m_back_to_sys_value(m_opt_id); } +void Field::on_edit_value() +{ + if (m_fn_edit_value) + m_fn_edit_value(m_opt_id); +} + wxString Field::get_tooltip_text(const wxString& default_string) { if (m_opt.tooltip.empty()) diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 704e0900b31..6ab464f2e20 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -95,6 +95,30 @@ class UndoValueUIManager UndoValueUI m_undo_ui; + struct EditValueUI { + // Bitmap and Tooltip text for m_Edit_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one. + const ScalableBitmap* bitmap{ nullptr }; + wxString tooltip { wxEmptyString }; + + bool set_bitmap(const ScalableBitmap* bmp) { + if (bitmap != bmp) { + bitmap = bmp; + return true; + } + return false; + } + + bool set_tooltip(const wxString& tip) { + if (tooltip != tip) { + tooltip = tip; + return true; + } + return false; + } + }; + + EditValueUI m_edit_ui; + public: UndoValueUIManager() {} ~UndoValueUIManager() {} @@ -105,6 +129,9 @@ class UndoValueUIManager bool set_undo_tooltip(const wxString* tip) { return m_undo_ui.set_undo_tooltip(tip); } bool set_undo_to_sys_tooltip(const wxString* tip) { return m_undo_ui.set_undo_to_sys_tooltip(tip); } + bool set_edit_bitmap(const ScalableBitmap* bmp) { return m_edit_ui.set_bitmap(bmp); } + bool set_edit_tooltip(const wxString& tip) { return m_edit_ui.set_tooltip(tip); } + // ui items used for revert line value bool has_undo_ui() const { return m_undo_ui.undo_bitmap != nullptr; } const wxBitmapBundle& undo_bitmap() const { return m_undo_ui.undo_bitmap->bmp(); } @@ -112,8 +139,17 @@ class UndoValueUIManager const wxBitmapBundle& undo_to_sys_bitmap() const { return m_undo_ui.undo_to_sys_bitmap->bmp(); } const wxString* undo_to_sys_tooltip() const { return m_undo_ui.undo_to_sys_tooltip; } const wxColour* label_color() const { return m_undo_ui.label_color; } + + // Extentions + + // Search blinker const bool blink() const { return m_undo_ui.blink; } bool* get_blink_ptr() { return &m_undo_ui.blink; } + + // Edit field button + bool has_edit_ui() const { return !m_edit_ui.tooltip.IsEmpty(); } + const wxBitmapBundle* edit_bitmap() const { return &m_edit_ui.bitmap->bmp(); } + const wxString* edit_tooltip() const { return &m_edit_ui.tooltip; } }; @@ -147,6 +183,8 @@ class Field : public UndoValueUIManager void on_back_to_initial_value(); /// Call the attached m_back_to_sys_value method. void on_back_to_sys_value(); + /// Call the attached m_fn_edit_value method. + void on_edit_value(); public: /// parent wx item, opportunity to refactor (probably not necessary - data duplication) @@ -162,6 +200,9 @@ class Field : public UndoValueUIManager t_back_to_init m_back_to_initial_value{ nullptr }; t_back_to_init m_back_to_sys_value{ nullptr }; + /// Callback function to edit field value + t_back_to_init m_fn_edit_value{ nullptr }; + // This is used to avoid recursive invocation of the field change/update by wxWidgets. bool m_disable_change_event {false}; bool m_is_modified_value {false}; diff --git a/src/slic3r/GUI/OG_CustomCtrl.cpp b/src/slic3r/GUI/OG_CustomCtrl.cpp index a3cb345b420..ebd9de9464c 100644 --- a/src/slic3r/GUI/OG_CustomCtrl.cpp +++ b/src/slic3r/GUI/OG_CustomCtrl.cpp @@ -278,6 +278,11 @@ void OG_CustomCtrl::OnMotion(wxMouseEvent& event) tooltip = *field->undo_to_sys_tooltip(); break; } + if (opt_idx < line.rects_edit_icon.size() && is_point_in_rect(pos, line.rects_edit_icon[opt_idx])) { + if (Field* field = opt_group->get_field(opt_key); field && field->has_edit_ui()) + tooltip = *field->edit_tooltip(); + break; + } } if (!tooltip.IsEmpty()) break; @@ -327,6 +332,13 @@ void OG_CustomCtrl::OnLeftDown(wxMouseEvent& event) event.Skip(); return; } + + if (opt_idx < line.rects_edit_icon.size() && is_point_in_rect(pos, line.rects_edit_icon[opt_idx])) { + if (Field* field = opt_group->get_field(opt_key)) + field->on_edit_value(); + event.Skip(); + return; + } } } @@ -565,17 +577,21 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos) return; } + wxCoord h_pos = draw_mode_bmp(dc, v_pos); + Field* field = ctrl->opt_group->get_field(og_line.get_options().front().opt_id); const bool suppress_hyperlinks = get_app_config()->get_bool("suppress_hyperlinks"); if (draw_just_act_buttons) { - if (field) - draw_act_bmps(dc, wxPoint(0, v_pos), field->undo_to_sys_bitmap(), field->undo_bitmap(), field->blink()); + if (field) { + const wxPoint pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap(), field->undo_bitmap(), field->blink()); + // Add edit button, if it exists + if (field->has_edit_ui()) + draw_edit_bmp(dc, pos, field->edit_bitmap()); + } return; } - wxCoord h_pos = draw_mode_bmp(dc, v_pos); - if (og_line.near_label_widget_win) h_pos += og_line.near_label_widget_win->GetSize().x + ctrl->m_h_gap; @@ -606,7 +622,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos) option_set.front().side_widget == nullptr && og_line.get_extra_widgets().size() == 0) { if (field && field->has_undo_ui()) - h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap(), field->undo_bitmap(), field->blink()) + ctrl->m_h_gap; + h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap(), field->undo_bitmap(), field->blink()).x + ctrl->m_h_gap; else if (field && !field->has_undo_ui() && field->blink()) draw_blinking_bmp(dc, wxPoint(h_pos, v_pos), field->blink()); // update width for full_width fields @@ -635,7 +651,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos) } if (field && field->has_undo_ui()) { - h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap(), field->undo_bitmap(), field->blink(), bmp_rect_id++); + h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap(), field->undo_bitmap(), field->blink(), bmp_rect_id++).x; if (field->getSizer()) { auto children = field->getSizer()->GetChildren(); @@ -746,7 +762,7 @@ wxPoint OG_CustomCtrl::CtrlLine::draw_blinking_bmp(wxDC& dc, wxPoint pos, bool i return wxPoint(h_pos, v_pos); } -wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmapBundle& bmp_undo_to_sys, const wxBitmapBundle& bmp_undo, bool is_blinking, size_t rect_id) +wxPoint OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmapBundle& bmp_undo_to_sys, const wxBitmapBundle& bmp_undo, bool is_blinking, size_t rect_id) { pos = draw_blinking_bmp(dc, pos, is_blinking); wxCoord h_pos = pos.x; @@ -765,7 +781,19 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBi h_pos += bmp_dim + ctrl->m_h_gap; - return h_pos; + return wxPoint(h_pos, v_pos); +} + +wxCoord OG_CustomCtrl::CtrlLine::draw_edit_bmp(wxDC &dc, wxPoint pos, const wxBitmapBundle *bmp_edit) +{ + const wxCoord h_pos = pos.x + ctrl->m_h_gap; + const wxCoord v_pos = pos.y; + const int bmp_w = get_bitmap_size(bmp_edit, ctrl).GetWidth(); + rects_edit_icon.emplace_back(wxRect(h_pos, v_pos, bmp_w, bmp_w)); + + dc.DrawBitmap(bmp_edit->GetBitmapFor(ctrl), h_pos, v_pos); + + return h_pos + bmp_w + ctrl->m_h_gap; } bool OG_CustomCtrl::CtrlLine::launch_browser() const diff --git a/src/slic3r/GUI/OG_CustomCtrl.hpp b/src/slic3r/GUI/OG_CustomCtrl.hpp index 269f847a22b..0d7cb620421 100644 --- a/src/slic3r/GUI/OG_CustomCtrl.hpp +++ b/src/slic3r/GUI/OG_CustomCtrl.hpp @@ -62,12 +62,14 @@ class OG_CustomCtrl :public wxPanel wxCoord draw_mode_bmp(wxDC& dc, wxCoord v_pos); wxCoord draw_text (wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width, bool is_url = false); wxPoint draw_blinking_bmp(wxDC& dc, wxPoint pos, bool is_blinking); - wxCoord draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmapBundle& bmp_undo_to_sys, const wxBitmapBundle& bmp_undo, bool is_blinking, size_t rect_id = 0); + wxPoint draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmapBundle& bmp_undo_to_sys, const wxBitmapBundle& bmp_undo, bool is_blinking, size_t rect_id = 0); + wxCoord draw_edit_bmp(wxDC& dc, wxPoint pos, const wxBitmapBundle* bmp_edit); bool launch_browser() const; bool is_separator() const { return og_line.is_separator(); } std::vector rects_undo_icon; std::vector rects_undo_to_sys_icon; + std::vector rects_edit_icon; wxRect rect_label; }; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 3fda23323b9..625cbbbba48 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -96,6 +96,14 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co }; field->m_parent = parent(); + if (edit_custom_gcode && opt.is_code) { + field->m_fn_edit_value = [this](std::string opt_id) { + if (!m_disabled) + this->edit_custom_gcode(opt_id); + }; + field->set_edit_tooltip(_L("Edit CustomG-code")); + } + field->m_back_to_initial_value = [this](std::string opt_id) { if (!m_disabled) this->back_to_initial_value(opt_id); diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index f754505dd4a..0df7c753fec 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -121,6 +121,8 @@ class OptionsGroup { std::function rescale_extra_column_item { nullptr }; std::function rescale_near_label_widget { nullptr }; + + std::function edit_custom_gcode { nullptr }; wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 94a2960679e..aef40170b78 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -188,6 +188,8 @@ void Tab::create_preset_tab() // Bitmaps to be shown on the "Undo user changes" button next to each input field. add_scaled_bitmap(this, m_bmp_value_revert, "undo"); add_scaled_bitmap(this, m_bmp_white_bullet, "dot"); + // Bitmap to be shown on the "edit" button before to each editable input field. + add_scaled_bitmap(this, m_bmp_edit_value, "edit"); fill_icon_descriptions(); set_tooltips_text(); @@ -601,6 +603,10 @@ void Tab::decorate() field->set_undo_tooltip(tt); field->set_undo_to_sys_tooltip(sys_tt); field->set_label_colour(color); + + if (field->has_edit_ui()) + field->set_edit_bitmap(&m_bmp_edit_value); + } if (m_active_page) @@ -1852,6 +1858,11 @@ static void validate_custom_gcode_cb(Tab* tab, const wxString& title, const t_co tab->on_value_change(opt_key, value); } +void Tab::edit_custom_gcode(const t_config_option_key& opt_key) +{ + MessageDialog(this, format_wxstr("Edit gcode for %1%", opt_key), this->title()).ShowModal(); +} + void TabFilament::create_line_with_near_label_widget(ConfigOptionsGroupShp optgroup, const std::string& opt_key, int opt_index/* = 0*/) { Line line {"",""}; @@ -2179,6 +2190,7 @@ void TabFilament::build() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("start_filament_gcode"); option.opt.full_width = true; option.opt.is_code = true; @@ -2189,6 +2201,7 @@ void TabFilament::build() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("end_filament_gcode"); option.opt.full_width = true; option.opt.is_code = true; @@ -2611,6 +2624,7 @@ void TabPrinter::build_fff() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("start_gcode"); option.opt.full_width = true; option.opt.is_code = true; @@ -2624,6 +2638,7 @@ void TabPrinter::build_fff() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("end_gcode"); option.opt.full_width = true; option.opt.is_code = true; @@ -2634,6 +2649,7 @@ void TabPrinter::build_fff() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("before_layer_gcode"); option.opt.full_width = true; option.opt.is_code = true; @@ -2644,6 +2660,7 @@ void TabPrinter::build_fff() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("layer_gcode"); option.opt.full_width = true; option.opt.is_code = true; @@ -2654,6 +2671,7 @@ void TabPrinter::build_fff() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("toolchange_gcode"); option.opt.full_width = true; option.opt.is_code = true; @@ -2664,6 +2682,7 @@ void TabPrinter::build_fff() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("between_objects_gcode"); option.opt.full_width = true; option.opt.is_code = true; @@ -2674,6 +2693,7 @@ void TabPrinter::build_fff() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("color_change_gcode"); option.opt.is_code = true; option.opt.height = gcode_field_height;//150; @@ -2683,6 +2703,7 @@ void TabPrinter::build_fff() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("pause_print_gcode"); option.opt.is_code = true; option.opt.height = gcode_field_height;//150; @@ -2692,6 +2713,7 @@ void TabPrinter::build_fff() optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup_title, opt_key, value); }; + optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); }; option = optgroup->get_option("template_custom_gcode"); option.opt.is_code = true; option.opt.height = gcode_field_height;//150; @@ -4823,6 +4845,13 @@ void Tab::fill_icon_descriptions() "the current option group.\n" "Click the BACK ARROW icon to reset all settings for the current option group to " "the last saved preset.")); + + m_icon_descriptions.emplace_back(&m_bmp_edit_value, L("EDIT VALUE"), + // TRN Description for "EDIT VALUE" + L("indicates that the settings were changed and are not equal to the last saved preset for " + "the current option group.\n" + "Click the BACK ARROW icon to reset all settings for the current option group to " + "the last saved preset.")); } void Tab::set_tooltips_text() diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index f0be456a5a7..6ec714fc280 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -213,6 +213,8 @@ class Tab: public wxPanel ScalableBitmap *m_bmp_non_system; // Bitmaps to be shown on the "Undo user changes" button next to each input field. ScalableBitmap m_bmp_value_revert; + // Bitmaps to be shown on the "Undo user changes" button next to each input field. + ScalableBitmap m_bmp_edit_value; std::vector m_scaled_buttons = {}; std::vector m_scaled_bitmaps = {}; @@ -386,6 +388,7 @@ class Tab: public wxPanel const std::map& get_category_icon_map() { return m_category_icon; } static bool validate_custom_gcode(const wxString& title, const std::string& gcode); + void edit_custom_gcode(const t_config_option_key &opt_key); bool validate_custom_gcodes(); bool validate_custom_gcodes_was_shown{ false };